I've got a base class and then several derived classes. I would like to overload the "<<" operator for these derived classes. For normal operators, i.e. '+', virtual functions do the trick. What I understand to be the standard convention is to declare
friend ostream& operator<<(ostream& out, MyClass& A);
within my class and then define the function after the class. A priori I would think adding virtual to the above definition would make it work, but after some thought (and errors from my compiler) I realize that doesn't make much sense.
I tried a different tack on a test case, where all the class members are public. For example:
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 b开发者_如何转开发ar;
}
///////////////////////
Bar bar = Bar();
cout << bar << endl; // outputs 'Foo', not 'Bar'
So in some way this is "polymorphism gone bad" -- the base class operator<< is being called rather than the derived class operator. In the above example, how do I make the correct operator get called for the derived class? And more generally, if my class has private members I want to protect, how can I correct the operator overloading while using the friend keyword?
You can use a virtual helper function. Here's a completely untested example, so excuse any syntax mistakes:
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);
}
Edit: Cleaned up per @Omnifarious suggestions.
Usually you just create a polymorphic print
method in the base class which is called by a single free friend function.
Make operator<<
a free function that forwards the call to a virtual
method of class Foo
.
See it in action.
With the proper code corrections in place, your code works fine; nothing to be done:
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. For accessing private
members, you can make this function as friend
in the desired class
.
精彩评论