【发布时间】:2009-10-11 05:28:39
【问题描述】:
我想为自定义类的对象控制写入流的内容,即cout。这在 C++ 中可能吗?在 Java 中,您可以覆盖 toString() 方法以实现类似目的。
【问题讨论】:
标签: c++
我想为自定义类的对象控制写入流的内容,即cout。这在 C++ 中可能吗?在 Java 中,您可以覆盖 toString() 方法以实现类似目的。
【问题讨论】:
标签: c++
在 C++ 中,您可以为 ostream 和您的自定义类重载 operator<<:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
这样你就可以在流上输出你的类的实例:
A x = ...;
std::cout << x << std::endl;
如果您的 operator<< 想要打印出 A 类的内部结构并且确实需要访问其私有和受保护成员,您也可以将其声明为友元函数:
class A {
private:
friend std::ostream& operator<<(std::ostream&, const A&);
int j;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.j << ")";
}
【讨论】:
friend,并且也在类的主体内 - 这样,您不必为包含运算符(和类)的命名空间执行using namespace ,但只要该类的对象是操作数之一,ADL 就会找到它。
dump 公共方法是肮脏且不必要的。在这里使用friend 非常好。您是否喜欢冗余方法或侵入性 friend 完全取决于个人喜好,尽管可以说引入了 friend 就是为了这个目的。
operator<<() 设为成员函数也行不通:您必须将其设为std::ostream 的成员函数才能接受std::ostream 类型的左操作数。
你也可以这样做,允许多态性:
class Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Base: " << b << "; ";
}
private:
int b;
};
class Derived : public Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Derived: " << d << "; ";
}
private:
int d;
}
std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }
【讨论】:
toString 行为。
在 C++11 中,to_string 最终被添加到标准中。
http://en.cppreference.com/w/cpp/string/basic_string/to_string
【讨论】:
ToString() 是在 all 对象的基类上定义的虚函数,因此被用作表达任何对象的字符串表示的标准方式。 std::string 上的这些函数仅适用于内置类型。 C++ 中的惯用方式是为自定义类型覆盖 << 运算符。
operator<< 的标准签名的“丑陋”,与 Java 的简单 String 语义相比,提示我说,to_string() 不仅是“一个有用的补充”,而且在 C++ 中执行此操作的新首选方法。如果像 OP 一样,需要类 A 的自定义字符串表示,只需在 class A 的定义下方编写 string to_string(A a) 就足够了。这与 Java 中的继承一起传播,并且可以像 Java 中一样组合(通过字符串添加)。无论如何,Java 中的非覆盖 toString() 的使用是有限的。
作为 John 所说的扩展,如果您想提取字符串表示并将其存储在 std::string 中,请执行以下操作:
#include <sstream>
// ...
// Suppose a class A
A a;
std::stringstream sstream;
sstream << a;
std::string s = sstream.str(); // or you could use sstream >> s but that would skip out whitespace
std::stringstream 位于<sstream> 标头中。
【讨论】:
问题已得到解答。但我想添加一个具体的例子。
class Point{
public:
Point(int theX, int theY) :x(theX), y(theY)
{}
// Print the object
friend ostream& operator <<(ostream& outputStream, const Point& p);
private:
int x;
int y;
};
ostream& operator <<(ostream& outputStream, const Point& p){
int posX = p.x;
int posY = p.y;
outputStream << "x="<<posX<<","<<"y="<<posY;
return outputStream;
}
这个例子需要理解运算符重载。
【讨论】: