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?
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.
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.)
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
I read in some sources that if we implements operator+ by operator=+ so we don't have define operator+ as "friend".
Someone can explain it?
An idea is to avoid duplicate code. See this example:
class A
{
int a = 0;
public:
A & operator+=(const A& other) { a += other.a; return *this; }
};
Then you could implement operator+ in terms of operator+= saving yourself the duplicate code, and keeping it as a free function:
A operator+(const A& lhs, const A& rhs) { A tmp(lhs); tmp += rhs; return tmp; }
Which means you now have two functions. And if you change the meaning of +=, the meaning of + changes too. Easier to maintain.
I would like to leave the two instances unchanged, and return a new one.
Currently I am doing it this way:
class myClass {
public:
myClass operator +(const myClass &obj) {
myClass ret = *this;
// some operation
return ret;
}
// functions...
};
It works, but I am not sure, if it is the correct way
Edit
The operator + is just an example. I'm just curious, how the immutable functions/methods should be written in C++
If myClass is supposed to be immutable under addition, you probably want to make operator+ a free function rather than a class member. (You might have to make it a friend function.)
myClass operator+(const myClass &lhs, const myClass &rhs) {
return myClass( /* some operation */ );
}
Note that both operands are taken by const reference, so you know you cannot accidentally change them (maintaining the immutability property). You're returning a new instance of myClass, which is now immutable. You construct and return the result in one step, because, if myClass really is immutable, you might not be able to default construct one and then set its value.
Here's a stupid example:
class myClass {
public:
explicit myClass(int x) : m_x(x) {}
friend myClass operator+(const myClass &lhs, const myClass &rhs);
private:
int m_x;
};
myClass operator+(const myClass &lhs, const myClass &rhs) {
return myClass(lhs.m_x + rhs.m_x);
}
If you really want to implement it as a class method, the method should be marked const to ensure the implementation doesn't accidentally mutate the left-hand instance.
Binary arithmetic operators (like operator+) are often defined in terms of the arithmetic self-assignment operators (like operator+=), which are obviously not immutable. If we add this method to myClass:
myClass &operator+=(const myClass &rhs) {
m_x += rhs.m_x;
return *this;
}
Then the common idiom for defining operator+ would be:
myClass operator+(const myClass &lhs, const myClass &rhs) {
myClass result = lhs;
result += rhs;
return result;
}
Now the implementation of operator+ doesn't require any of the private members of the class, so it no longer needs to be declared as a friend function.
I am trying to overload += operator for my template Polynom class in a way so I would be able to use both Polynoms and constants as argument.
I wrote a constructor and following operator inside my class:
Polynom(const T& num = 0) {
coefs.push_back(num);
}
friend Polynom& operator += (Polynom& lhs, const Polynom& rhs) {
...
}
And it works fine, I am able to use: poly += 1;. When compiler runs into something likes that what does it do? It sees that there is no += operator that uses these arguments:
(Polynom<int>& lhs, const int)
But there is one for:
(Polynom<int>& lhs, const Polynom& rhs)
So, it tries to convert const int to const Polynom&? And it uses constructor for that, right? But then why doesn't this declaration work when adding a constant:
Polynom& operator += (Polynom& rhs) {
...
}
Compiler says "no match for operator +=".
When passing an int to a function taking a const Polynom&, the compiler is able to construct a temporary Polynom object from the int that is then bound to the const Polynom& parameter. However this doesn't happen with the Polynom& parameter because temporaries cannot be bound to non const references.
You need to show us the template code or your smallest compilable code that demonstrates the issue.
Try creating a method that accepts an integer parameter:
friend Polynom& operator+=(const Polynom& lhs, int constant);
I'm confused about your notation Polynom<int> which indicates your Polynom class is a template.
suppose i have 2 objects of a class and it has one int data member.
i want to add those integer data to other object and store the output in the first obj's data member.I can overload the + operator and use the statement like below
X+Y //where X and Y are objects of one class.
if i have to add like below
X+10// here i want to add 10 to the data member of X.
for above also i can overload the operator +.
but if i have 10+X and i want to add 10 to the data member of X how could i do it?
The same way:
MyClass operator+(MyClass const& lhs, MyClass const& rhs);
MyClass operator+(MyClass const& lhs, int rhs);
MyClass operator+(int lhs, MyClass const& rhs);
(operator+ should not normally be a member.)
If you overload operator+, you'll also want to overload +=. One
frequent idiom involved implementing + in terms of +=. This can
be more or less automated (if you have a lot of classes
supporting operators) by defining something like:
template<typename DerivedType>
class ArithmeticOperators
{
public:
friend DerivedType operator+(
DerivedType const& lhs,
DerivedType const& rhs)
{
DerivedType result(lhs);
result += rhs;
return result;
}
// And so on for the other operators...
protected:
~ArithmeticOperators() {}
};
template<typename DerivedType, typename OtherType>
class MixedArithmeticOperators
{
public:
friend DerivedType operator+(
DerivedType const& lhs,
OtherType const& rhs)
{
DerivedType result(lhs);
result += rhs;
return result;
}
friend DerivedType operator+(
OtherType const& lhs,
DerivedType const& rhs)
{
DerivedType result(rhs);
result += lsh;
return result;
}
// And so on: non-commutative operators only have the
// first.
protected:
~MixedArithmeticOperators() {}
};
, then deriving from whatever is needed: in your case:
class MyClass : public ArithmeticOperators<MyClass>,
MixedArithmeticOperators<MyClass, int>
You have to create an overloaded operator as a free function with the correct parameter order:
// This will match "int + YourClass" additions
YourClass operator+(int Left, const YourClass & Right)
{
// If your addition operation is commutative, you can just call the other
// version swapping the arguments, otherwise put here your addition logic
return Right + Left;
}
If the operator needs to fiddle with the internals of your class you can make it friend.
As others pointed out, there are some best/common practices that you should follow if you implement operator+, I suggest you to have a look to the great C++-FAQ on operator overloading for more info about them.
Don't overload the operator + as a member function of the class.
You can either define a global function operator + with two parameters or make operator + a friend of your class (In that case you should be having a parameterized constructor to convert 10 to an object of your class-type).
Define a non-member stand-alone free function as:
sample operator+(int leftOperand, const sample & rightOperand)
{
//...
}
Although you can do that using a global operator+, I would advise not to do it.
Only use operator overloading for data types for which the operators are immediately clear, e.g.:
complex numbers
strings (+,- ok, but * probably doesn't make much sense here)
The risk with overloaded operators is that the compiler may perform unwanted conversions, especially if you didn't make the single-argument constructor explicit.
You should define a non-member friend function
YourClass operator+(const YourClass &a, const YourClass&b) {
// do the math here
}
it should be friend to get to the private members of YourClass. Also you should create constructor for YourClass that takes int.
In this way you've got one operator+ and for every other then int you just create another constructor.
I'm trying to overload the assignment operator and would like to clear a few things up if that's ok.
I have a non member function, bool operator==( const MyClass& obj1, const myClass& obj2 ) defined oustide of my class.
I can't get at any of my private members for obvious reasons.
So what I think I need to do is to overload the assignment operator. And make assignments in the non member function.
With that said, I think I need to do the following:
use my functions and copy information using strcpy or strdup. I used strcpy.
go to the assignment operator, bool MyClass::operator=( const MyClass& obj1 );
Now we go to the function overloading (==) and assign obj2 to obj1.
I don't have a copy constructor, so I'm stuck with these:
class Class
{
private:
m_1;
m_2;
public:
..
};
void Class::Func1(char buff[]) const
{
strcpy( buff, m_1 );
return;
}
void Class::Func2(char buff[]) const
{
strcpy( buff, m_2 );
return;
}
bool Class& Class::operator=(const Class& obj)
{
if ( this != &obj ) // check for self assignment.
{
strcpy( m_1, obj.m_1 );
// do this for all other private members.
}
return *this;
}
bool operator== (const Class& obj1, const Class& obj2)
{
Class MyClass1, MyClass2;
MyClass1 = obj1;
MyClass2 = obj2;
MyClass2 = MyClass1;
// did this change anything?
// Microsofts debugger can not get this far.
return true;
}
So as you can probably tell, I'm completely lost in this overloading. Any tips? I do have a completed version overloading the same operator, only with ::, so my private members won't lose scope. I return my assignments as true and it works in main. Which is the example that I have in my book.
Will overloading the assignment operator and then preforming conversions in the operator== non member function work? Will I then be able to assign objects to each other in main after having completed that step?
You have a couple of obvious mistakes here and there is some confusion about what you are actually trying to achieve. Firstly, the assignment operator operator = is meant to copy the value from one instance to another. The return value of the assignment operator is almost always a non constant reference to the target of the copy, so that you can chain assignments:
Class & operator=(const Class &rhs)
{
// copy the members
return *this;
}
The comparison operator operator == is meant to perform a comparison of two instances. It returns a boolean true if they are equal:
boolean operator==(const Class &rhs) const
{
// check if they are equal
return something;
}
The confusion is why are you trying to copy values around, or maybe assign to the instances in the comparison operator?
Op== isn't the assignment operator. T& Op= (const T&) is.
bool operator==(const T& lhs, const T& rhs) is the operation to compare two Ts. It returns true if lhs is equal to rhs, for whatever definition of "equal" you want to code.
I am guessing that you want to compare the two objects. In that case, you can just overload the operator == in class "Class". You don't need assignment operator.
class Class
{
public:
Class(int i) : m_i(i){}
bool operator==( const Class& rhs)
{
return m_i == rhs.m_i;
}
private:
int m_i;
};
int main()
{
Class t1(10), t2(10);
bool b = (t1 == t2);
}
I am not sure whether I understood the question correctly. But if you trying to check the equality using a non-member function and can't do this only because you can't access the private members of the class, then you can declare the non-member function as a friend function and use it like this:
class Test
{
public:
Test(int i) : m_i(i){}
private:
int m_i;
friend bool operator==(Test& first, Test& second);
};
bool operator==(Test& first, Test& second)
{
return first.m_i == second.m_i;
}
int main()
{
Test t1(10), t2(10);
bool b = (t1 == t2);
}