C++ multiple operator overloads for the same operator
Solution 1
The canonical form of implementing operator+()
is a free function based on operator+=()
, which your users will expect when you have +
. +=
changes its left-hand argument and should thus be a member. The +
treats its arguments symmetrically, and should thus be a free function.
Something like this should do:
//Beware, brain-compiled code ahead!
class MyClass {
public:
MyClass& operator+=(const MyClass &rhs) const
{
// code for adding MyClass to MyClass
return *this;
}
MyClass& operator+=(int rhs) const
{
// code for adding int to MyClass
return *this;
}
};
inline MyClass operator+(MyClass lhs, const MyClass& rhs) {
lhs += rhs;
return lhs;
}
inline MyClass operator+(MyClass lhs, int rhs) {
lhs += rhs;
return lhs;
}
// maybe you need this one, too
inline MyClass operator+(int lhs, const MyClass& rhs) {
return rhs + lhs; // addition should be commutative
}
(Note that member functions defined with their class' definition are implicitly inline
. Also note, that within MyClass
, the prefix MyClass::
is either not needed or even wrong.)
Solution 2
Yes.
These operator functions are just ordinary functions with the special names operator@
. There's no restriction that they cannot be overloaded. In fact, the <<
operator used by iostream is an operator with multiple overloads.
Solution 3
Yes, you can overload operators like this. But I'm not sure what "switch case" you are referring to. You can live with one overload if you have a converting constructor
class MyClass{
...
// code for creating a MyClass out of an int
MyClass(int n) { ... }
...
inline const MyClass MyClass::operator+(const MyClass &addend) const {
cout<<"Adding MyClass+MyClass"<<endl;
...//Code for adding MyClass with MyClass
}
...
};
No switch is needed at all. This is eligible if "MyClass" logically represents a number.
Notice that you should overload these operators by non-member functions. In your code 5 + c1
would not work, because there is no operator that takes an int as left hand side. The following would work
inline const MyClass operator+(const MyClass &lhs, const MyClass &rhs) {
// ...
}
Now if you keep the converting constructor you can add the int by either side with minimal code overhead.
Related videos on Youtube
eladidan
Software Engineer in Quixey, working on large-scale, distributed app crawling
Updated on June 27, 2020Comments
-
eladidan almost 4 years
I know I can answer this question easily for myself by generatin the code and see if it compiles. But since I couldn't find a similar question, I thought it's knowledge worth sharing. Say I am overloading the + operator for MyClass. Can I overload it multiple times. Different overload for different types. Like this:
class MyClass{ ... inline const MyClass operator+(const MyClass &addend) const { cout<<"Adding MyClass+MyClass"<<endl; ...//Code for adding MyClass with MyClass } inline const MyClass operator+(const int &addend) const { cout<<"Adding MyClass+int"<<endl; ...//Code for adding MyClass with int } ... }; int main(){ MyClass c1; MyClass c2; MyClass c3 = c1 + c2; MyClass c4 = c1 + 5; } /*Output should be: Adding MyClass+MyClass Adding MyClass+in*/
The reason I want to do this is that I am building a class that I want to be as optimized as possible. Performance is the biggest concern for me here. So casting and using switch case inside the operator + overloaded function is not an option. I f you'll notice, I made both the overloads inline. Let's assume for a second that the compiler indeed inlines my overloads, then it is predetermined at compile time which code will run, and I save the call to a function (by inlining) + a complicated switch case scenario (in reality, there will be 5+ overloads for + operator), but am still able to write easily read code using basic arithmetic operators. So, will I get the desired behavior?
-
David Rodríguez - dribeas almost 14 years@paercebal: He is implementing the a sum, not an increment. If he was implementing
operator+=
, then returning a reference would be fine (after modifying the internal state), buta+b
is not meant to modify thea
, but rather produce a third value that differs from botha
andb
.
-
-
sbi almost 14 yearsJohannes, that implicit converting constructor might not be a good idea. For one, IME implicit conversions usually turn out to be a bad idea sooner or later anyway, but also because eladidan wants to do this because "I am building a class that I want to be as optimized as possible." In that case, overloads are better anyway.
-
Matt Joiner almost 14 yearsI feel bad cluttering your answer with a comment. Spot on.
-
sbi almost 14 yearsOh, and mindlessly copying
inline blah MyClass::
intoMyClass
doesn't seem like you at all.:)
-
Matthieu M. almost 14 years+1 for the correct form. However I would probably use Boost.Operators to generate the free-functions for free :)
-
vad almost 14 yearsVery basic qn: Your definition for + requires lhs to be a const whereas the code requires you to write lhs += rhs. It seems to be you either need to change your code or your definition. Am I right?
-
sbi almost 14 years@Anon: That was a major blurb of mine.
<hangs_head_in_shame>
I went and fixed it, and took the opportunity to add my standard disclaimer. -
Bill almost 14 yearsI think operator+ should do:
MyClass temp = lhs; temp += rhs; return temp;
. Otherwise, if I do:MyClass a = b + c;
, thenb
changes. -
eladidan almost 14 years@Bill.Not so. lhs is received byVal. Since we return that shallow copy, then we do not change the original parameter and we don't create any unnecessary instances of MyClass. Your solution is valid only if we receive lhs byref (MyClass& lhs) and if we overload the "=" operator;
-
sbi almost 14 years@eladidan:
MyClass temp = lhs
invokes the copy constructor, not the assignment operator, but otherwise you are right.