简体   繁体   中英

Overload operators as member function or non-member (friend) function?

I am currently creating a utility class that will have overloaded operators in it. What are the pros and cons of either making them member or non-member ( friend ) functions? Or does it matter at all? Maybe there is a best practice for this?

I'd go with "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices": if you can do it as non-member function, do it as non-member function (in the same namespace).

One of the reasons: it works better with implicit type conversion. An Example: You have a complex class with an overloaded operator*. If you want to write 2.0 * aComplexNumber, you need the operator* to be a non-member function.

Another reason: less coupling. Non-member-functions a less closely coupled than member functions. This is almost always a good thing.

Each operator has its own considerations. For example, the << operator (when used for stream output, not bit shifting) gets an ostream as its first parameter, so it can't be a member of your class. If you're implementing the addition operator, you'll probably want to benefit from automatic type conversions on both sides, therefore you'll go with a non-member as well, etc...

As for allowing specialization through inheritance, a common pattern is to implement a non-member operator in terms of a virtual member function (eg operator<< calls a virtual function print() on the object being passed).

If you plan on implementing streaming operators (<< and >>) then they will be non-members methods because your object is on the left of the operator.

If you plan on implementing ->, () or [] they are naturally member methods.

For the others (comparison and mathematical) you should check out Boost.Operators , it really helps.

For example, if you want to implement the following operators:

MyClass& MyClass::operator+=(int);
MyClass operator+(const MyClass&, int);
MyClass operator+(int, const MyClass&);

You only have to write:

class MyClass: boost::operator::addable<MyClass,int> // no need for public there
{
public:
  MyClass& operator+=(int);
private:
};

The 2 operator+ will be automatically generated as non-members which will let you benefit from automatic conversions. And they will be implemented efficiently in term of operator+= so you write code only once.

If you are implementing op, then most probably you need to implement op=. ie if you are overloading + operator, then you should implement +=. Make sure that you are returning const to an object if you are doing post-increment or overloading + operator. So, if you overload operator + , then implement it as a non-member operator and use += operator inside it. For eg.

const A operator+(const A& lhs, const A& rhs)
{
   A ret(lhs);
   ret += rhs;
   return ret;
}

For binary operators, one limitation of member functions is that the left object must be of your class type. This can limit using the operator symmetrically.

Consider a simple string class:

class str
{
public:
    str(const char *);
    str(const str &other);
};

If you implement operator+ as a member function, while str("1") + "2" will compile, "1" + str("2") will not compile.

But if you implement operator+ as a non-member function, then both of those statements will be legal.

There is nothing like best practices but it depends on the operator you are overloading ..

For eg .

  1. >> and << can't be overloaded as member functions .

  2. Suppose you want to do like this : obj1 = 2 * obj2 then go for non-member function .

For binary operator overloading member function takes only 1 parameter (invoking object is impcliitly passed ) whereas non-member function takes 2 parameters .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM