[ Team LiB ] |
![]() ![]() |
Gotcha #86: Friend versus Member OperatorsAn overloaded operator should allow application of any conversions its argument types support: class Complex { public: Complex( double re = 0.0, double im = 0.0 ); // . . . }; For example, the Complex constructor permits a conversion from the predefined numeric types to a Complex. The non-member add function allows this conversion to be performed implicitly on either of its arguments: Complex add( const Complex &, const Complex & ); Complex c1, c2; double d; add(c1,c2); add(c1,d); // add( c1, Complex(d,0.0) ) add(d,c1); // add( Complex(d,0.0), c1 ) The non-member operator + function below permits the same implicit conversions: Complex operator +( const Complex &, const Complex & ); c1 + c2; operator +(c1,c2); // same as above c1 + d; operator +(c1,d); // same as above d + c1; operator +(d,c1); // same as above However, if we implement the binary addition of Complex with a member function, we introduce an asymmetry with respect to implicit conversion: class Complex { public: // member operators Complex operator +( const Complex & ) const; // binary Complex operator -( const Complex & ) const; // binary Complex operator -() const; // unary // . . . }; // . . . c1 + c2; // fine. c1.operator +(c2); // fine. c1 + d; // fine. c1.operator +(d); // fine. d + c1; // error! d.operator +(c1); // error! The compiler cannot apply an implicit, user-defined conversion to the first argument of a member function. If such a conversion is part of the desired interface, this implies that a member implementation of the binary operator is inappropriate. Non-member friends allow conversions on their first argument. Members allow only is-a conversion. (See also Gotcha #42.) ![]() |
[ Team LiB ] |
![]() ![]() |