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.