为什么我的重载<<运算符不工作?

mbr*_*ero 3 c++

我试图了解如何正确地重载"<<"运算符,以便我可以使用

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)

我在这里错过了什么?

BoB*_*ish 5

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项,(或在线查找摘要).

  • OP忘了解除引用. (2认同)