如何实现多个插入运算符(<<) for a C++ class?

问题描述 投票:0回答:1

我使用

cout
ofstream
输出我的类对象。我知道插入运算符
<<
是将对象转换为字符串或打印它的标准方法。我想在项目的不同部分使用不同的格式。

我希望该类有许多不同的字符串格式。然而,该类只能有一个插入运算符。

在C++中解决这个问题的常用方法有哪些?

我使用的一个解决方案是让多个函数返回字符串。我的理解是,重载插入运算符是输出对象的最常见方法,我希望有这种解决方案。

使用不同的格式听起来像是策略模式。我想模板也是解决很多问题的强大工具。我对这两种解决方案都不熟悉。

这是一个演示该问题的代码示例:

#include <iostream>
#include <sstream>

class Point {
  public:
    Point(int x, int y): x(x), y(y) {}

    std::string to_string() {
      std::ostringstream stream;
      stream << "(" << x << ", " << y << ")";
      return stream.str();
    }   

    friend std::ostream& operator<<(std::ostream& out, const Point& p) {
      return out << p.x << " " << p.y;
    }   

  private:
    int x, y;
};

int main() {
  Point p { 4, 2 };
  std::cout << p << std::endl;
  std::cout << p.to_string() << std::endl;
}

我想摆脱

to_string
函数并使用插入运算符来获取所有格式。定义插入操作符使用哪种格式的简单方法是什么?应该可以改变对象的格式。

课程可能有两种以上不同的形式。

c++ class templates ostream
1个回答
1
投票

您可以为此任务定义自己的 I/O 流操纵器,类似于字符串的

std::quoted

例如:

#include <iostream>

class Point {
  public:
    Point(int x, int y): x(x), y(y) {}
  private:
    int x, y;
    friend struct s_Point_printer;
};

struct s_Point_printer {
    const Point &m_pt;
    const bool m_parenthesis;

    s_Point_printer(const Point &pt, bool parenthesis) : m_pt(pt), m_parenthesis(parenthesis) {}

    void printTo(std::ostream &out) const {
        if (m_parenthesis)
            out << "(" << m_pt.x << ", " << m_pt.y << ")";
        else
            out << m_pt.x << " " << m_pt.y;
    }

    friend std::ostream& operator<<(std::ostream &out, const s_Point_printer &printer) {
        printer.printTo(out);
        return out;
    }
};

s_Point_printer with_parens( const Point& pt ) {
    return s_Point_printer{pt, true};
}

s_Point_printer without_parens( const Point& pt ) {
    return s_Point_printer{pt, false};
}

int main() {
  Point p { 4, 2 };
  std::cout << without_parens(p) << std::endl; // prints "4 2"
  std::cout << with_parens(p) << std::endl;    // prints "(4, 2)"
}

在线演示

或者:

class Point {
  public:
    static int point_xalloc;

    Point(int x, int y): x(x), y(y) {}

    friend std::ostream& operator<<(std::ostream& os, const Point& pt) {
        if (os.iword(Point::point_xalloc) == 1)
            return os << "(" << pt.x << ", " << pt.y << ")";
        else
            return os << pt.x << " " << pt.y;
    }

  private:
    int x, y;
};
 
int Point::point_xalloc = std::ios_base::xalloc();

std::ios_base& with_parens(std::ios_base& os) {
    os.iword(Point::point_xalloc) = 1;
    return os;
}
 
std::ios_base& without_parens(std::ios_base& os) {
    os.iword(Point::point_xalloc) = 0;
    return os;
}

int main() {
  Point p { 4, 2 };
  std::cout << without_parens << p << std::endl; // prints "4 2"
  std::cout << with_parens << p << std::endl;    // prints "(4, 2)"
}

在线演示

© www.soinside.com 2019 - 2024. All rights reserved.