Overload operators as member function or non-membe

2019-01-08 00:09发布

问题:

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?

回答1:

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 (e.g. operator<< calls a virtual function print() on the object being passed).



回答2:

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.



回答3:

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.



回答4:

If you are implementing op, then most probably you need to implement op=. i.e. 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;
}


回答5:

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.



回答6:

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

For e.g .

  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 .