C++, polymorphism and friendly <<

  • Thread starter Thread starter Peter
  • Start date Start date
Joined
3/24/08
Messages
63
Points
18
Suppose I have a base class Domain and derived class DomainFloating.

Domain is abstract, since it defines an interface:
Domain.h:
virtual double deltaCentral() const = 0;
virtual double gammaCentral() const = 0;
virtual double uApprox() const = 0;
virtual double vApprox() const = 0;
and so forth. But it's not pure abstract since it provides its own functions that are to be used by all its derivative classes, DomainFloating and DomainFixed, for example:
Domain.h:
double transform( double S, double t ) const;

double unTransform( double x, double tau ) const;
I've overloaded the << operator for Domain:
Domain.h:
friend ostream& operator<<(ostream& output, const Domain& domain);

and I've also overloaded the << operator for DomainFloating:
DomainFloating.h:
friend ostream& operator << (ostream& output, const DomainFloating& d);
Originally, I was mystified why << for a derived class doesn't chain to the << for a base class, but then it became obvious: these aren't class members, so they have no entries in the vtable and hence don't act polymorphically.

Fine.

But then I have an operational question. I would like to define << for the derived class like this:
PHP:
DomainFloating.cpp:
ostream& operator << ( ostream& output, const DomainFloating& d )
{
   output
      << Domain(d)
      <<  "--- DomainFloating -------------" <<  endl
      <<  "xBarLeft:  "       << d.xBarLeft  <<  endl
      <<  "xBarRight: "       << d.xBarRight <<  endl
      <<  "Nleft:     "       << d.Nleft     <<  endl
      <<  "Nright:    "       << d.Nright    <<  endl
      <<  "--------------------------------" <<  endl;

   return output;  // for multiple << operators.
}
The problem, of course, is that I can't instantiate Domain() because it's abstract. The only way I know how to do this is by doing something retarded, like this:
PHP:
DomainFloating.cpp:
ostream& operator << ( ostream& output, const DomainFloating& d )
{
   output
      <<  d.all       << endl;
      <<  d.the       << endl;
      <<  d.variables << endl;
      <<  d.in        << endl;
      <<  d.the       << endl;
      <<  d.base      << endl;
      <<  d.class     << endl;
      <<  d."Domain"  << endl;
      <<  "--- DomainFloating -------------" <<  endl
      <<  "xBarLeft:  "       << d.xBarLeft  <<  endl
      <<  "xBarRight: "       << d.xBarRight <<  endl
      <<  "Nleft:     "       << d.Nleft     <<  endl
      <<  "Nright:    "       << d.Nright    <<  endl
      <<  "--------------------------------" <<  endl;

   return output;  // for multiple << operators.
}
There must be a more intelligent/convenient way of doing this.

What is it?
 
I don't know the professional way, but I create a virtual "printhelper" function in both Domain and DomainFloating that does the actual printing.

Code:
virtual void printhelper( ostream& os ) const;

The body of this in DomainFloating might call Domain::printhelper( os ).

Then I write a generic << overload that is not a member function; do this once and let polymorphism do the rest.

Code:
ostream& operator<<( ostream& os, const Domain& d )
{
d.printhelper( os );
return os;
}
 
Nice. Kind of round-a-bout, but much more palatable than the brain-dead way of doing this. Thanks!

I wonder WWSMD?

(SM == Scott Meyers) :D
 
I like Doug's solution. But one other way which probably isn't portable is instead of

output << Domain(d)

use

output << *(static_cast<Domain *>(&d))

compiler thinks &d is (Domain *) so it concludes that d is Domain and so uses the desired operator<<.
 
Back
Top Bottom