user3230221
user3230221

Reputation: 11

Not getting right output when Overloading the '+' operator in Calculator Program for c++

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

Answers (3)

bolov
bolov

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':

  • input: first operand: c1
  • input: second operand: c2
  • output: the result 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:

  • the first operand is the this object of the method (operator overload).
  • the second operand is the only argument of the method.
  • the result is the return of the method.

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:

  • the first operand is the first parameter of the function (operator overload).
  • the second operand is the second parameter of the function.
  • the result is the return of the function.

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

Paul Evans
Paul Evans

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

juanchopanza
juanchopanza

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

Related Questions