Reputation:
Hi I have been trying to analyze the following code that uses operation overloading.
#include <iostream>
using namespace std;
#define DBG(str) cout << str << endl
class Integer {
int n;
public:
Integer(int _n) : n(_n) { DBG("A"); };
Integer(const Integer& i) : n(i.n) { DBG("B"); };
Integer& operator=(const Integer& i) { DBG("C"); n = i.n; return *this; };
Integer& operator+=(const Integer& i) { DBG("D"); n += i.n; return *this; };
friend Integer operator+(const Integer& a, const Integer& b);
friend Integer operator*(const Integer& a, const Integer& b);
friend ostream& operator<<(ostream& os, const Integer& i);
};
Integer operator+(const Integer& a, const Integer& b) {
DBG("E"); return Integer(a.n + b.n);
}
Integer operator*(const Integer& a, const Integer& b) {
DBG("F"); return Integer(a.n * b.n);
}
ostream& operator<<(ostream& os, const Integer& i) {
DBG("G"); os << i.n; return os;
}
int main() {
Integer n1(1), n2(2);
Integer n = 5 + n1 + 2 * n2;
cout << n << endl;
}
and the result comes out to be...
A // constructor called when n1 is created
A // constructor called when n2 is created
A // when is this called?
A // when is this called?
F // called when 2 * n2 is operated
A // called when Integer(a.n * b.n) is created in the multiplication function
E // called when 5 + n1 is operated
A // called when Integer(a.n + b.n) is created in the addition function
E // called when (5 + n1) + (2 * n2) is operated
A // called when Integer is created in the addition function
G // called when n is printed using cout
5 // value of n
Now what I'm having trouble with the most is the third and fourth print of A. In the sentence Integer n = 5 + n1 + 2 * n2;
the object n is being created and the right value is assigned to n, so a copy constructor should be called? What I think should happen is the constructor should be called for making a temporary object of (5 + n1 + 2 * n2)
and then by copying it to n, the copy constructor should be called. What am I understanding wrong?
Could you please explain what is happening? Thank you in advance.
Upvotes: 2
Views: 122
Reputation: 4854
Friend function is used in operator overloading only when the first parameter of the operator function is not an object of the target class for which the operator function is defined.
In your case, Integer
:
Integer operator+(const Integer& a, const Integer& b) {
DBG("E"); return Integer(a.n + b.n);
}
Integer operator*(const Integer& a, const Integer& b) {
DBG("F"); return Integer(a.n * b.n);
}
, the first parameter is indeed an object of type Integer
which is your target class. What you probably want is to be able to use your Integer
object as operands along with primitive integer types.
Change your friend function signatures to:
Integer operator+(const int& a, const Integer& b) {
DBG("E"); return Integer(a + b.n);
}
Integer operator*(const int& a, const Integer& b) {
DBG("F"); return Integer(a * b.n);
}
Note that a
is used instead of a.n
because when an operator function is defined as friend, both operands are passed as parameters.(unlike non-friend operator functions where the first operand is a calling object). So the a
contains a value of type int
and not a value of type Integer
.
The anonymous calls to the constructor containing
DBG("A")
is a result of the implicit conversions happening when 5 and 2 are being converted fromint
toInteger
.
This is unreliable although your code may work. Hope this helps.
Upvotes: 0
Reputation: 37607
Problem is in this line:
Integer n = 5 + n1 + 2 * n2;
There is no operator+
for int
and Integer
, but compiler silently did a implicit conversion from int
to Integer
, since by default all single argument constructors can be used as conversion method.
Here is your live code (improved a bit).
This is one of dangerous features of C++ so there is explicit
keyword to be used before constructor. If you add it:
explicit Integer(const Integer& i) : n(i.n) { DBG("B"); };
Compiler will report an error since implicit conversion now can't be performed and there is no operator+(int, const Integer&)
and operator*(int, const Integer&)
.
Upvotes: 5
Reputation: 768
Your operator+
and operator*
functions receive an const Integer&
as parameter.
When this line is calculated (5 + n1 + 2 * n2
) 5 and 2 will be auto-converted to Integer
.
If you want them to not be converted, you should consider creating operators for int
as parameter.
EDIT: You can also use explicit constructor.
For example: explicit Integer(int _n){...}
//thanks for the comment @formerlyknownas_463035818
Upvotes: 2