开发者

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

开发者 https://www.devze.com 2022-12-14 13:23 出处:网络
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) func开发者_JAVA技巧tions? Or does it m

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) func开发者_JAVA技巧tions? 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 (e.g. 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.


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.


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;
}


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 .

0

精彩评论

暂无评论...
验证码 换一张
取 消