Effective C++ Note 19: member functions, non-member functions and friend functions
main points:
1. Virtual functions must be member functions.
2. Operator >> and << are never member functions.
3. Only non-member functions get type conversions on their left-most argument.
4. Everything else should be a member functions.
Point No. 1 is without debate, so we'll just past it by.
Operator >> and << are never member functions
When we use operator >> and <<, we use it this way:
cin>>C;
cout<<C;
where C is an instance of some class. So if we decide to write operator >> and << for our class, the right thing to do is to define them as non-member functions. If you define them as member functions, your will have to put C on the left, as shown below:
class String {
public:
String(const char *value);
...
istream& operator>>(istream& input);
ostream& operator<<(ostream& output);
private:
char *data;
};
String C;
C>> cin; // legal, but contrary
// to convention
C<< cout; // ditto
That would confuse everyone. So here comes the right one:
istream& operator>>(istream& input, String& string)
{
delete [] string.data;
[i] read from input into some memory, and make string.data
point to it[/i]
return input;
}
ostream& operator<<(ostream& output,
const String& string)
{
return output << string.data;
}
Only non-member functions get type conversions on their left-most argument
Consider overloading operator + for String like this:
const String String::operator + (const String & rhs){...};
String a="Hello";
char * b="world";
a=a+b; // fine
a=b+a; // error!
Why does the first one works while the other doesn't? Because when we do a=a+b, its treated like this:
String temp(b); // implicit conversion
a=a+temp;
The implicit conversion is possible because we have a constructor that takes const char * as the argument. However, implicit type conversion will never happen to the object on which a member function is invoked. So the only way to make a=b+a work is to write operator + as non-member function like this:
const String operator + (const String & a, const String & b){...};