-1
#include<iostream>

using namespace std;

class Complex
{
    public:
        int real;
        int imagine;


        Complex(int r = 0, int l = 0)
        {
            this -> real = r;
            this -> imagine = l;
        }
          friend ostream & operator<<(ostream &o, Complex &c);
          friend Complex operator+(Complex c1, Complex c2);
          friend Complex operator-(Complex c1, Complex c2);
          friend Complex operator*(Complex c1, Complex c2);
          friend Complex operator/(Complex c1, Complex c2);

};

ostream & operator<<(ostream &o, Complex &c)
{
    o << c.real << "+" << c.imagine << "i" << endl;
}

Complex& operator+(Complex c1, Complex c2)
{
    Complex temp;
    temp.real = c1.real + c2.real;
    temp.imagine = c1.imagine + c2.imagine;
    return &temp;
}

int main()
{
    Complex c1(2,3);
    Complex c2(3,2);
    Complex c3 = c1 + c2;
    cout << c1 + c2;

}

The following code is giving error. If I assign to a Complex number c3 and then pass to cout. Also, during operator overloading, how to determine when to use reference (For ex. for '<<' overloading we return reference of type ostream) and when to use value?

  • A [good c++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) is always the way out of confusion. – theWiseBro Apr 17 '20 at 05:34
  • I'm not sure what the question is, exactly. You seem to know that `operator<<` MUST return an `ostream`. And I'm pretty sure you know that not returning an `ostream` is the bug you're facing, but after that...? You are asking what you should return? Why you need to return a value? – user4581301 Apr 17 '20 at 05:36
  • What is the error? Have you read [the basic rules and idioms for operator overloading](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading)? – JaMiT Apr 17 '20 at 05:37
  • Use a value when you want something to be copied, use a reference when you don't want something to be copied. Don't return a reference to something that is local to a function. Be consistent. That about sums it up. – john Apr 17 '20 at 05:40
  • What is the difference between cout << c3 or cout << c1+c2? both return complex number type. The result of c1+c2 should still function right?? – Rohit Sai Kiran Apr 17 '20 at 05:42
  • 2
    @RohitSaiKiran Yes and the reason it doesn't is that you forgot `const`. `ostream & operator<<(ostream &o, const Complex &c)` The `const` is very important here. Not using a reference would also work `ostream & operator<<(ostream &o, Complex c)`. The relavent rule is that you cannot bind a non-const reference to a temporary. I know I'm repeating what is above, but any reasonable C++ book would explain this. – john Apr 17 '20 at 05:50
  • Note: The declared `friend Complex operator+(Complex c1, Complex c2);` does not match the implemented `Complex& operator+(Complex c1, Complex c2)` Remove the `&`. Then you must fix the return statement. `return &temp;` does not return a reference. It returns the address of `temp`. The compiler will not accept this. Worse, you never ever want to return a pointer or a reference to a non-`static` local variable. The variable vanishes at the end of the function and you wind up returning a reference to a dead variable. This can sometimes fool you by looking like it worked. – user4581301 Apr 17 '20 at 05:53
  • @user4581301 I'm guessing that function got changed in attempt to fix the `cout << c1+c2` problem that the OP described above. But he picked the wrong function to fix. – john Apr 17 '20 at 05:54
  • I know the question got changed because there wasn't a `main` the first time I passed through. Didn't notice `+` had also been modified. – user4581301 Apr 17 '20 at 05:56
  • @user4581301 I wasn't talking about the question. I'm just guessing at the history of this code before the OP posted to stack overflow. – john Apr 17 '20 at 05:56
  • Ah. Mistake B was the result of shotgun debugging mistake A. A reasonable conclusion. – user4581301 Apr 17 '20 at 06:07

2 Answers2

1
ostream & operator<<(ostream &o, Complex &c)
{
    o << c.real << "+" << c.imagine << "i" << endl;
}

should be

ostream & operator<<(ostream &o, const Complex &c)
{
    return o << c.real << "+" << c.imagine << "i" << endl;
}

(declaration should be changed accordly)

temporary cannot bind to no const lvalue reference.

and missing return lead to UB.

Complex& operator+(Complex c1, Complex c2)
{
    Complex temp;
    temp.real = c1.real + c2.real;
    temp.imagine = c1.imagine + c2.imagine;
    return &temp;
}

should be

Complex operator+(Complex c1, Complex c2)
{
    Complex temp;
    temp.real = c1.real + c2.real;
    temp.imagine = c1.imagine + c2.imagine;
    return temp;
}

so return type matches return, declaration matches definition, you no longer return dangling pointer (as returning reference/pointer of local variable).

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

Have a good day Mr Rohit.

The Complex sum

There is a problem at your code at two different parts of it. The first one is at your line return &temp, the Complex object that you create at that function should be returned itself, not a reference of it. You return an object (value, as you specify at your question) in this case as a new complex is built taking the sum of two complex (the function returns a new object).

The Complex printing

By the other hand, the << operator overload should return a value of the type that you are specifying at that same function (an ostream & object), which is the same that you use as the first parameter of the function. This is done for being able to concatenate more than one << one after each other. Of course, if you are not modifying the value of the Complex object in that function you should name it const. The same applies at the friend declaration. You return a reference (ostream &) in order to be able to concatenate more outputs later, e.g. cout << c1+c2 << "Hello world" << endl;

Bonus observations

I recommend you to modify the constructor as well as I have modified at your code below, in this case you can see assignments to member variables of the instance whose values are specified at the parenthesis after them.

By the way, if you are using friend modifier for your functions then maybe member variables should be kept at private section of the class, else the friend modifier is not needed.

The Code

Your code should end like this one, which works:

#include <iostream>

using namespace std;

class Complex
{
    public:
        Complex(int r = 0, int l = 0) : real(r), imagine(l) {} // Modified for simplicity purposes
        friend ostream& operator<<(ostream &o, const Complex &c);
        friend Complex operator+(const Complex &c1, const Complex &c2);
        friend Complex operator-(const Complex &c1, const Complex &c2);
        friend Complex operator*(const Complex &c1, const Complex &c2);
        friend Complex operator/(const Complex &c1, const Complex &c2);
    private:
        int real; // Beware of using int instead of doubles when dividing
        int imagine;
};

ostream& operator<<(ostream &os, const Complex &c) // If no changes are done to c, then const.
{
    os << c.real << "+" << c.imagine << "i"; // It is not a good practice to add an endl here
    return os;
}

Complex operator+(const Complex &c1, const Complex &c2) // No reference returned (and use const &).
{
    Complex temp;
    temp.real = c1.real + c2.real;
    temp.imagine = c1.imagine + c2.imagine;
    return temp; // No reference is returned, a new object is.
}

int main()
{
    Complex c1(2,4);
    Complex c2(3,2);
    Complex c3 = c1 + c2;
    cout << c3 << endl; // Why not using this directly if the sum is above?, endl goes here.
    return 0; // This is a good practice.
}


I hope that my comments would help you to write better apps.

To know more: https://learn.microsoft.com/en-us/cpp/standard-library/overloading-the-output-operator-for-your-own-classes?view=vs-2019

sisco_0
  • 1
  • 2
  • *// Why not using this directly if the sum is above?* The question was why did `cout << c3;` work, but the mathematically identical `cout << c1 +c2;` did not. The answer to that is because of the bugs in operators `<<` and `+`. – user4581301 Apr 17 '20 at 06:10