我试图了解如何正确地重载"<<"运算符,以便我可以使用
std::cout << my_object;
Run Code Online (Sandbox Code Playgroud)
打印有用的调试消息.特别是,我需要为每个子类都有一个<<的实现,所以我声明<<在超类中是虚拟的.
现在我坚持使用以下代码
#include <iostream>
using namespace std;
class Shape {
public:
virtual ~Shape() { };
virtual ostream& operator<<(std::ostream &strm) = 0;
};
class Square : public Shape {
int size;
public:
Square() { size = 10; }
~Square() { }
ostream& operator<<(std::ostream &strm) {
return strm << "a square with size " << size;
}
};
int main() {
Square *my_square = new Square();
cout << "my_square is " << my_square << "\n";
}
Run Code Online (Sandbox Code Playgroud)
(我认为)应该工作,但不是.使用"<<"时得到的是my_square的指针值被打印,而不是重载<<的结果.
$ ./a.out
my_square is 0xcacc20
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?
operator<<不能成为会员功能.这是因为参数的顺序.流必须先来.
调用重载运算符时,例如:
os << object;
Run Code Online (Sandbox Code Playgroud)
编译器将尝试查找两者
os.operator<<(object);
Run Code Online (Sandbox Code Playgroud)
和
operator<<(os, object);
Run Code Online (Sandbox Code Playgroud)
(这个规则可能相当复杂,我不会试图在这里描述它们.)
因为流始终位于左侧,所以永远不会找到您的成员函数,因为它必须被调用为:
object.operator<<(os);
Run Code Online (Sandbox Code Playgroud)
你需要编写一个免费的函数,如:
ostream& operator<<(std::ostream &strm, Square const& square) {
return strm << "a square with size " << square.size();
}
Run Code Online (Sandbox Code Playgroud)
(Square::size()返回size成员的地方).
然后你需要记住取消引用你的指针:
std::cout << *my_square << '\n';
Run Code Online (Sandbox Code Playgroud)
虽然我认为没有理由my_square在这个例子中动态分配.只需将其作为局部变量粘贴在堆栈上即可.
如果此处的目标最终是能够打印任何 Shape&,并且打印输出遵循"真实"类型,则需要创建:
virtual std::ostream& print(std::ostream&) const = 0;
Run Code Online (Sandbox Code Playgroud)
在Shape基类中,并在每个派生类中重写它,然后有一个自由函数:
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape.print(os);
}
Run Code Online (Sandbox Code Playgroud)
通常建议在类型非成员函数上创建所有二元运算符,这样两个参数都被平等对待,并且操作仍然是可交换的.参见Scott Meyers,Effective C++(第3版),第24项,(或在线查找摘要).
| 归档时间: |
|
| 查看次数: |
1515 次 |
| 最近记录: |