Provide a friend operator<< that calls a protected virtual function:
class Base {
public:
friend ostream& operator<< (ostream& o, const Base& b)
{ b.print(o); return o; }
//...
protected:
virtual void print(ostream& o) const; //or "=0;" if "Base" is an ABC
};
class Derived : public Base {
protected:
virtual void print(ostream& o) const;
};
Now all subclasses of Base merely provide their own "
print(ostream&) const"
member function (they all share the common "<<" operator). This
technique
allows friends to act as if they supported dynamic binding.