Question

Which C++ operators can not be overloaded at all without friend function?

Était-ce utile?

La solution

The operators where the left-hand-side operand is not the class itself. For example cout << somtething can be achieved via defining a std::ostream& operator<<(std::ostream& lhs, Something const & rhs); function, and marking them as friend inside the class.

EDIT: Friending is not needed, ever. But it can make things simpler.

Autres conseils

You only need a friend declaration if:

  1. You define the operator as a standalone function outside the class, and
  2. The implementation needs to use private functions or variables.

Otherwise, you can implement any operator without a friend declaration. To make this a little bit more concrete... one can define various operators both inside and outside of a class*:

 // Implementing operator+ inside a class:
 class T {
   public:
    // ...
    T operator+(const T& other) const { return add(other); }
    // ...
 };

 // Implementing operator+ outside a class:
 class T {
   // ...
 };

 T operator+(const T& a, const T& b) { return a.add(b); }

If, in the example above, the "add" function were private, then there would need to be a friend declaration in the latter example in order for operator+ to use it. However, if "add" is public, then there is no need to use "friend" in that example. Friend is only used when granting access is needed.

*There are cases where an operator cannot be defined inside a class (e.g. if you don't have control over the code of that class, but would still like to provide a definition where that type is on the left-hand side, anyway). In those cases, the same statement regarding friend declarations still holds true: a friend declaration is only needed for access purposes. As long as the implementation of the operator function relies only on public functions and variables, a friend declaration is not needed.

The only reason to use friend function is to access the private(including protected) member variable and functions.

You never need a friend function. If you don't want the operator to be a member (usually the case for binary operators which do not modify their operands), there's no requirement for it to be a friend. There are two reasons one might make it a friend, however:

  1. in order to access private data members, and
  2. in order to define it in the class body (even though it is not a member), so that ADL will find it

The second reason mainly applies to templates, but it's common to define operators like + and - in a template base class, in terms of += and -=, so this is the most common case.

Operator overloading and friendship are orthogonal concepts. You need to declare a function (any function) friend whenever it needs access to a private member of the type, so if you overload an operator as a function that is not a member and that implementation needs access to the private members, then it should be friend.

Note that in general it is better not to declare friends, as that is the highest coupling relationship in the language, so whenever possible you should implement even free function overloads of operators in terms of the public interface of your type (allowing you to change the implementation of the type without having to rewrite the operators). In some cases the recommendation would be to implement operatorX as a free function in terms of operatorX= implemented as a public member function (more on operator overloading here)

There is an specific corner case, with class templates, where you might want to declare a free function operator as a friend of the template just to be able to define it inside the template class, even if it does not need access to private members:

template <typename T>
class X {
   int m_data;
public:
   int get_value() const { return m_data; }

   friend std::ostream& operator<<( std::ostream& o, X const & x ) {
      return o << x.get_value();
   }
};

This has the advantage that you define a single non-templated function as a friend in a simple straightforward way. To move the definition outside of the class template, you would have to make it a template and the syntax becomes more cumbersome.

You need to use a friend function when this is not the left-hand-side, or alternatively, where this needs to be implicitly converted.

Edit: And, of course, if you actually need the friend part as well as the free function part.

operators [] -> =

Must be a member functions.

Other binary operators acceptable for overloading can be write in function form or in memeber-function form. Operators acceptable for overloading is all unary and binary C++ operators except

: . :: sizeof typeid ?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top