我有一个基类,然后有几个派生类。我想重载“<<”这些派生类的运算符。对于普通算子,即'+',虚函数可以解决问题。我理解的标准惯例是声明
friend ostream& operator<<(ostream& out, MyClass& A);
在我的课程中,然后在课程后定义函数。先验我认为将虚拟添加到上面的定义会使它工作,但经过一些思考(和编译器的错误)我意识到这没有多大意义。
我在测试用例上尝试了不同的方法,所有的类成员都是公开的。例如:
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'
因此,在某种程度上,这是“多态性变坏” - 基类运算符&lt;&lt;被调用而不是派生类操作符。在上面的例子中,如何为派生类调用正确的运算符?更一般地说,如果我的班级有我想要保护的私人成员,我怎样才能在使用friend关键字时纠正运算符重载?
答案 0 :(得分: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);
}
修改:根据@Omnifarious建议清理。
答案 1 :(得分:2)
通常,您只需在基类中创建一个多态print
方法,该方法由一个免费的朋友函数调用。
答案 2 :(得分:1)
将operator<<
设为免费功能,将调用转发给virtual
类的Foo
方法。
<强> See it in action 强>
答案 3 :(得分:1)
通过适当的代码更正,您的代码可以正常工作;没有什么可做的:
ostream& operator<<(ostream& out, Foo& foo) {
out << "Foo" << endl; // 'out' and not 'cout'
return out; // returns 'out' and not 'foo'
}
ostream& operator<<(ostream& out, Bar& bar) {
out << "Bar" << endl; // 'out' and not 'cout'
return out; // returns 'out' and not 'bar'
}
Demo。要访问private
成员,您可以在所需的friend
中将此功能设为class
。