Reputation: 11
I can't seem to get the right output for #3. The output is supposed to be 12, but I get a junk. I don't really understand overloading, so can someone explain it to me, please?
I tried different returns, and other things, but I can't seem to get it right. Would someone please explain?
I'm not getting any errors, right now, just junk output.
#include <iostream>
using namespace std;
class Calculator
{
private:
public:
double total;
double newNum;
//default constructor
Calculator()
{
total = 0;
}
double clear()
{
total = 0;
return total;
}
void add(double num)
{
num += y;
}
void subtract(double num)
{
num -= y;
}
void multiply(double num)
{
total *= num;
}
void divide (double num)
{
total /= num;
}
double display()
{
return total;
}
//parameterized constructor
Calculator(double newNum)
{
x = newNum;
}
Calculator operator+(Calculator c)
{
return Calculator(y);
}
};
int main()
{
Calculator mycalc;
mycalc.clear();
mycalc.add(4.52);
mycalc.add(3.789);
mycalc.divide(2.6);
mycalc.multiply(3.12);
mycalc.subtract(2.678);
cout << mycalc.display() << endl; // prints out "7.2928"
mycalc.clear();
mycalc.add(5.0);
cout << mycalc.display() << endl; // prints out "5"
//advanced stuff #1: add a constructor
Calculator calc1;
cout << calc1.display() << endl; //prints out 0
//advanced stuff #2: add a parameterized constructor
Calculator calc2(5);
cout << calc2.display() << endl; //prints out 5
//advanced stuff #3: Define calculator addition (overload the '+' operator)
Calculator calc3(7);
calc1 = calc2 + calc3;
cout << calc1.display() << endl; //prints out 12
//advanced stuff #4: Create an 'undo' method for the calculator
// mycalc.undo();
// mycalc.undo();
// cout << mycalc.display()<< endl; //prints out 7.2928
return 0;
}
Upvotes: 0
Views: 662
Reputation: 75844
I don't really understand overloading, so can someone explain it to me, please?
An operator can be overloaded as a class member or outside class definition.
Let's consider this code:
Calculator c1, c2, c_result;
c_result = c1 + c2;
The operator +
has 3 'components':
c1
c2
c_result
An operator overload is like a function with the two operands as arguments and the result as the return. From now on I will use operator overload and function/class member interchangeably.
When you overload as a class member:
class Calculator {
private:
int x;
public:
Calculator operator+(const Calculator &c) const {
// ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
// ^ result ^ ^^ second operand ^^
Calculator result;
result.x = x + c.x; // equivalent to result.x = this->x + c.x;
return result;
}
};
Here the second operand is passed to the function as the only parameter, and the function return is used as the result of the operator. But what happens with the first operand? Well, since this is a class method, this method is called on the first operand object, so the code from early on
c_result = c1 + c2;
is equivalent to (becomes):
c_result = c1.operator+(c2);
Here you can clearly see that the operator is called like a method of the c1
object.
So the first operand is actually the object on which the overload is called.
To sum up:
this
object of the method (operator overload).When you overload as an outside class definition:
class Calculator {
private:
int x;
public:
friend Calculator operator+(const Calculator &c1, const Calculator &c2);
};
Calculator operator+(const Calculator &c1, const Calculator &c2) {
//^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
//^result^ ^^ first operand ^^ ^^ second operand ^^
Calculator result;
result.x = c1.x + c2.x;
return result;
}
The two operands are passed as the two arguments of the function and the return is used as the result of the operator. So the code:
c_result = c1 + c2;
is equivalent to (becomes):
c_result = operator+(c1, c2);
Here you can clearly see that the operator is called like a function.
The friend
declaration is needed so that the function (which is not a class method) can access the private member x
of the class Calculator
.
To sum up:
Now let's talk a bit about type qualifiers. Because you are dealing with classes, the best practice is to pass the parameters by reference and not by value, so that the whole object is not copied to the method/function scope. But with references you can (accidentally) modify the original object, so you need to make them const
:
c_result = c1 + c2;
The operator + doesn't modify c1
or c2
, so any references to them must be const
:
Calculator operator+(const Calculator &c) const {
The argument (the second operand) has the type const Calculator &
.
You specify that the first operand is constant, by appending const
to the class method. This specifies that the this
object (the object on which the method is called, in this case the first operand) will not be modified by the method.
Calculator operator+(const Calculator &c1, const Calculator &c2) {
The both parameters, i.e. the both operands are constant references.
Please note that you can make your operator + to change the operands, but it is best to make the operator overload as close as possible to the expected behaviour of a plus operator.
Hope this helps. This applies to all operators. Here is a list where you can see what prototype has each operator in C++.
Upvotes: 0
Reputation: 27577
You want something more like:
Calculator operator+(const Calculator& c) const
{
return x + c.x;
}
but don't really understand what your y
data member is supposed to do. Think you should get rid of it and make x
private
.
Upvotes: 1
Reputation: 227508
First of all, you have a y
data member that is never initialized. So when you do this:
return Calculator(y);
You are returning a Calculator
instantiated with a garbage value. But that looks like a very strange addition operator. You probably want something like
Calculator operator+(const Calculator& c) const
{
Calculator tmp = c;
tmp.add(x);
return tmp;
}
A better approach is to overload +=
, and express the operator as a non-member. This ensures symmetry between LHS and RHS. This is particularly important in your case because you want implicit conversions from numerical types:
Calculator operator+(const Calculator& lhs, const Calculator& rhs)
{
Calculator tmp = lhs;
tmp += rhs;
return tmp;
}
This makes both c + 3.14
and 3.14 + c
valid expressions, where c
is a Calculator
instance.
Upvotes: 2