I have two classes, lets call them A and B. And I overloaded operator+= in class A. Now I want to do something like this:
A += B + B + B
And class B doesn't have overloaded operator+, which is a problem because the evaluation is right to left (it wants to add all Bs and then += the result to A).
Is there any way to achieve my goal without actually overloading operator+ for class B?
Is there any way to achieve my goal without actually overloading operator+ for class B?
In a word, no.
A::operator+= takes a B as input, so if you want A += B + B + B to work, you need a way of adding B objects together to produce a new B that += can take as input, and that is exactly what operator+ is meant for.
This is possible.
Instead of overloading the addition operator, you can make B implicitly convertible to and from an arithmetic type. A demo that requires no overloading of operator+ for B as per requirement, yet allows the exact expression that you desire:
struct B {
B() = default;
// this constructor makes B convertible from int
B(int){}
// this operator makes B convertible to int
operator int() {
return 42;
}
};
struct A {
A& operator+=(const B&) {
return *this;
}
// alternative:
// if you use this, then B does not need to convert from int
// A& operator+=(int)
};
int main() {
A A;
B B;
A += B + B + B;
}
Related
Python 3 allows overloading of *.
For example,
a*b
Allows a to define the result by providing a __mul__ method.
If however that method returns NotImplemented, the __rmul__ method on b is called (if it exists) to give the result. This is documented here.
One advantage of this is that I can make on object b that operates on a without knowing the class of a.
Is there an equivalent to __rmul__ in C++, or a way of achieving the same or a similar thing?
Correct me if I'm wrong, but according to my understanding, you need to overload an operator for 2 different classes.
You can do something like this as under:
#include <iostream>
class A
{
public:
int integer;
};
class B
{
public:
double decimal;
};
//A * B
double operator*(A a, B b)
{
return a.integer * b.decimal;
}
int main()
{
A a{12}; B b{2};
double c = a * b;
std::cout << c;
}
In the above example, I've overloaded operator* to multiply 2 objects of type A and B. But it only works for a * b, not b * a. So you can do something like this:
//B * A
double operator*(B b, A a)
{
return a.integer * b.decimal;
}
I define a global non-member method for + overloading
Like
ClassA operator+(const ClassA& a, const ClassB& b);
{
blah blah ;
}
In the communicative one, I can use
1)
ClassA operator+(const ClassB& b, const ClassA& a)
{
return operator+(a,b);
}
2)
ClassA operator+(const ClassB& b, const ClassA& a)
{
return a + b;
}
Any difference between 1 and 2?
Beyond the obvious difference pointed out first by #barakmanos in the comments ("the second one is more readable"), there is another technical difference.
Assume for a second, the following definitions:
struct B;
struct A
{
void operator+(B const&) const { ::std::cout << "member\n"; }
friend void operator+(A const&, B const&) { ::std::cout << "friend\n"; }
};
struct B { };
Now, consider the following three statements:
operator+(A(), B());
A().operator+(B());
A() + B();
The first one obviously calls the friend (free) function, the second one calls the member. However, the third one would call either if the other was not defined. In this special case, it cannot find a better match and would thus be ill formed. There are a few ways to modify this behaviour, e.g. if the member function was different in const-requirements, the expression could be correct and just lead to a larger overload set.
This demonstrates the difference in your two expressions: operator+(a,b) only considers free functions and not member functions overloading the binary plus operator.
In fact, the C++ standard has an example for another difference:
A() + B() only does argument dependent lookup, while operator+(A(), B()) does a normal function lookup. This means that the following is an error (taken from C++11 §13.3.1.2.10):
struct A { };
void operator + (A, A);
struct B {
void operator + (B);
void f ();
};
A a;
void B::f() {
operator+ (a,a); // error: global operator hidden by member
a + a; // OK: calls global operator+
}
I have this class definition:
class foo{
public:
foo();
foo(const int& var);
foo(const foo& var);
~foo();
const foo operator +(const foo& secondOp) const;
private:
int a;
//plus other values, pointers, e.t.c.
};
Also I have made this implementation for '+' operator overloading:
const foo foo::operator +(const foo& secondOp) const{
//I want here to check if i have one operand or two...
if ((FIRST_OPERAND.a!=0) && (secondOp.a==0)){
cout << "ERROR, second operand is zero";
return FIRST_OPERAND;
}
else if ((FIRST_OPERAND.a==0) && (secondOp.a!=0)){
cout << "ERROR, first operand is zero";
return secondOp;
}
}
When i write in main():
foo a(2);
foo b;
foo c;
//I want here to print the ERROR and
//return only the values of a
c = a + b;
Ηow can i return the value of the first operand if the second operand is zero and vice versa?
You're almost there. Since it's a member function, the first operand is *this, so replace FIRST_OPERAND.a with this->a or just a.
However, it might be better to make it a non-member function to allow conversions on both operands (i.e. to be able to write a + 2 or 2 + a). It will need to be a friend in order to access the private member(s).
friend foo operator +(const foo& firstOp, const foo& secondOp);
Also, it's best not to return a const value as that prevents moving from the return value.
It is the compiler that checks the syntaxical correctness of the program. It is unable to distinguish whether you indeed wanted to write
c = a;
that is to do the assignment or you wanted to write
c = a + b;
The both statements are correct.
It is a so-called logical error. The compiler is unable to see what we thoght.
For your line c = a; The assignment operator is implemented by the compiler (just shallow copying the object memory).
That is the reason your code compiles "without the second operand".
If you wish to disallow using the assignment operator - hide it. E.g. by implementing with the private access modifier.
You have to define this function as a friend function
friend Int operator + (int first, Int &second);
this function can perform obj + 2 or 2 + obj.
Int operator + (int first, Int& second){
second.a += first;
return second;
}
Let's say we have this class A:
class A
{
public:
int a;
A(int b)
{
a = b;
}
};
I would like to create a + overload such that I could use it like this
A a(1),b(2),c(3),&d;
d = a + b + c;
without modifying the content of each object. The next logical thing would be allocating a new chunk of memory each time like this:
A &operator+ (const A &b)
{
A *c = new A(a+b.a);
return *c;
}
But this would create a new problem: intermediate results are lost, causing memory leaks.
I could have easily solved this problem by making a static function that takes three A object references and stores the sum of the first two in the third, but I'm willing to bet that there must be some way to make + overload happen the way I want.
So the question is: is there any way I could use a chain of operator overloads that do not modify the operands without causing memory leaks?
You can simply use pass by value and do this:
A operator+ (A other) //pass by value
{
other.a += a;
return other;
}
Or, since the member a is publicly accessible, you can (rather should) make operator+ a non-member function as:
A operator+(A left, A const &right)
{
left.a += right.a;
return left;
}
Notice that the first argument is accepted by value, and second by reference. In this way, you don't need to declare a local variable in the function. You can use the first parameter; after all it is local to the function, you can do whatever you want to do with it: in this case, we just add right.a to it, and return it.
A better design of class would be this: (read the comments)
class A
{
int a; //make it private
public:
A(int b) : a(b) //use member initialization list
{
}
A& operator+=(A const & other) //add `+=` overload, as member of the class
{
a += other.a;
return *this;
}
};
//and make `+` non-member and non-friend
A operator+(A left, A const & right)
{
left += right; //compute this in terms of `+=` which is a member function
return left;
}
There is no need to use pointers inside operator+. You can allocate the intermediate object in the stack and then return it:
A operator+ (const A &b)
{
A c(a+b.a);
return c;
}
Or just:
A operator+ (const A &b)
{
return A(a+b.a);
}
Or even simpler:
A operator+ (const A &b)
{
return a+b.a;
}
Since this implicitly calls A::A(int).
Note that I removed the reference from the return type. You can't return a non-const reference to a local.
Then you would use it this way:
A a(1),b(2),c(3),d;
d = a + b + c;
Note that d is no longer a reference.
d1 + 4 works but 4 + d1 doesn't even though 4 can be converted implicitly to a GMan. Why aren't they equivalent?
struct GMan
{
int a, b;
GMan() : a(), b() {}
GMan(int _a) : a(_a), b() {}
GMan(int _a, int _b) : a(_a), b(_b) {}
GMan operator +(const GMan& _b)
{
GMan d;
d.a = this->a + _b.a;
d.b = this->b + _b.b;
return d;
}
};
int main()
{
GMan d1(1, 2), d(2);
GMan d3;
d3 = d1 + 4;
d3 = 4 + d1;
}
A call x + y is translated by the C++ compiler into either of the following two calls (depending on whether x is of class type, and whether such a function exists):
Member function
x.operator +(y);
Free function
operator +(x, y);
Now C++ has a simple rule: no implicit conversion can happen before a member access operator (.). That way, x in the above code cannot undergo an implicit conversion in the first code, but it can in the second.
This rule makes sense: if x could be converted implicitly in the first code above, the C++ compiler wouldn’t know any more which function to call (i.e. which class it belongs to) so it would have to search all existing classes for a matching member function. That would play havoc with C++’ type system and make the overloading rules even more complex and confusing.
This answer is correct. Those points then entail the canonical way of implementing such operators:
struct GMan
{
int a, b;
/* Side-note: these could be combined:
GMan():a(),b(){}
GMan(int _a):a(_a),b(){}
GMan(int _a, int _b):a(_a),b(_b){}
*/
GMan(int _a = 0, int _b = 0) : a(_a), b(_b){} // into this
// first implement the mutating operator
GMan& operator+=(const GMan& _b)
{
// the use of 'this' to access members
// is generally seen as noise
a += _b.a;
b += _b.b;
return *this;
}
};
// then use it to implement the non-mutating operator, as a free-function
// (always prefer free-functions over member-functions, for various reasons)
GMan operator+(GMan _a, const GMan& _b)
{
_a += b; // code re-use
return _a;
}
And so on for other operators.