In these cases I prefer to implement the functionality in a public method (virtual, most of the times). The operator << receives a reference to the object and calls the virtual method.
Printable View
I think it's the other way around. If everything is passed by reference, my design requires no copy operations. If you put the text in a std::string and then pass it to the op<< for strings, you create a temporary copy of the data: the string itself!
The clients are supposed to call the operator<< and not the method print(). The point is: do we care? There is no integrity issue. The only problem is that the public interface is bloated with one more name. If you think this is too bad, make print() private and 'friend' the operator<<. I usually don't.Code:#include <iostream>
class A
{
public:
virtual void print (std::ostream & os) const
{ os << "Object of class A" << std::endl; }
virtual ~A () {}
};
inline std::ostream & operator<< (std::ostream & os,
const A & a)
{
a.print (os);
return os;
}
class B : public A
{
public:
virtual void print (std::ostream & os) const
{ os << "Object of class B" << std::endl; }
};
using namespace std;
int main ()
{
A * p, * q; // Note: both are pointers to A
p = new A; // Object of base class
q = new B; // Object of derived class
cout << *p // Prints: "Object of class A"
<< *q // Prints: "Object of class B"
<< endl;
delete p;
delete q;
return 0;
}
Oh, and you might want B's print() to show the inherited part of the object by calling A's print():
In this case, if you decide to hide print() from the clients, you would have to make it protected, not private.Code:class B : public A
{
public:
virtual void print (std::ostream & os) const
{
os << "Object of class B. Base: ";
A::print (os);
}
//...
If I leave print() public, you might argue that my operator<< is just syntax sugar, but... yum! :-)
I don't see the importance of inheritance here at all. You still write two methods to call through yet another method....
That is fine because the overloaded operator<< cannot be a virtual member function, so making use of a virtual print function is normal. If you want, you can keep only the overloaded operator<< as the public interface by declaring it as a friend of the base class, then having the virtual print function be private (or at least protected), i.e., implement the non-virtual interface idiom.Quote:
Originally Posted by whiteflags
Of course, this only makes sense if inheritance is used, otherwise it would be unnecessary work, hence comocomocomo's preference betrays a possible overuse of inheritance ;)
Dunno, I don't find that terribly interesting: when not using inheritance, you also just need to write the operator<< once. In my opinion, the main advantage of using a print member function is that it can be virtual, and in fact the typical reason for having a print member function in addition to operator<< is that it is virtual.Quote:
Originally Posted by comocomocomo
I'm reading Scott Meyers' "Effective C++, 3rd edition". I'm still with item 19, but I followed some cross references and ended up in item 46: "Define non-member functions inside templates when type conversions are desired". The title does not mention it, but the trick suggested requires the use of 'friend'.
Basically, we have a class that should behave as a number (complex, rational... whatever). We define operator overloads (sum, product..) outside the class because we want automatic type conversions on both parameters.
Then we tempatise the whole design. The class becomes a template. The external operators become templates too. And then the automatic conversions don't work anymore!
The compiler won't try to cast the parameters to the template instantiation because it still hasn't decided which template instace to use.
The solution: 'friend' the desired operators instantiation from within the class template. The purpose is not letting them access the internals, but have them declared (or should I say instantiated...).
Isn't it amazing.