重载<<运算符和继承的类

and*_*dge 9 c++ polymorphism inheritance operators

我有一个基类,然后是几个派生类.我想为这些派生类重载"<<"运算符.对于普通算子,即'+',虚函数可以解决问题.我所理解的标准惯例是宣布

friend ostream& operator<<(ostream& out, MyClass& A);
Run Code Online (Sandbox Code Playgroud)

在我的课程中,然后在课程后定义函数.先验我认为将虚拟添加到上面的定义会使它工作,但经过一些思考(和编译器的错误)我意识到这没有多大意义.

我在一个测试用例上尝试了不同的方法,所有的类成员都是公开的.例如:

class Foo{
 //bla
};

ostream& operator<<(ostream& out, Foo& foo){
  cout << "Foo" << endl;
  return foo;
}

class Bar : public Foo{
 //bla
};

ostream& operator<<(ostream& out, Bar& bar){
  cout << "Bar" << endl;
  return bar;
}

///////////////////////

Bar bar = Bar();
cout << bar << endl; // outputs 'Foo', not 'Bar' 
Run Code Online (Sandbox Code Playgroud)

所以在某种程度上这是"多态变坏" - 基类运算符<<被调用而不是派生类运算符.在上面的例子中,如何为派生类调用正确的运算符?更一般地说,如果我的班级有我想要保护的私人成员,我怎样才能在使用friend关键字时纠正运算符重载?

Osc*_*orz 6

您可以使用虚拟助手功能.这是一个完全未经测试的例子,所以请原谅任何语法错误:

virtual ostream& Foo::print(ostream& out) const {
    return out << "Foo";
}

virtual ostream& Bar::print(ostream& out) const {
    return out << "Bar";
}

// If print is public, this doesn't need to be a friend.
ostream& operator<<(ostream& out, const Foo& foo) {
    return foo.print(out);
}
Run Code Online (Sandbox Code Playgroud)

编辑:根据@Omnifarious建议清理.