Question

I am trying to implement a class COMPLEX in C++ and overload the arithmetic operators as well as the '<<' and '>>' operators for input/output. Individually and also when cascaded the arithmetic operators work as expected - but i am unable to obtain correct results when trying to execute statements such as:

cout &lt&lt "something" &lt&lt complex1 + complex2 &lt&lt "\n";

where complex1 and complex2 are objects of the class COMPLEX.

snippets of class definition:

class COMPLEX{
    int a;  // Real part
    int b;  // Imaginary part
public:
    COMPLEX operator = (COMPLEX );
    COMPLEX operator + (COMPLEX ) const;
    friend istream& operator &gt&gt (istream &, COMPLEX &);
    friend ostream& operator &lt&lt (ostream &, COMPLEX &);
-snip-
}


COMPLEX COMPLEX::operator = (COMPLEX t_c) {
    return COMPLEX(a = t_c.a, b = t_c.b);
}

COMPLEX COMPLEX::operator + (COMPLEX t_c) const{
    return COMPLEX(a + t_c.a, b + t_c.b);
}

istream& operator &gt&gt (istream &i_s, COMPLEX &t_c){
    i_s &gt&gt t_c.a &gt&gt t_c.b;
    return i_s;
}

ostream& operator &lt&lt (ostream &o_s, COMPLEX &t_c){
    o_s &lt&lt t_c.a &lt&lt "+" &lt&lt t_c.b &lt&lt "i";
    return o_s;
}

apart from this i have also overloaded operator.

When ever i try to cascade << with any other overloaded operator, the overloaded << friend function is not getting called. Instead the operator is getting called and the result of that is being displayed.

Was it helpful?

Solution

The problem is that your stream insertion operator is defined as

friend ostream& operator << (ostream &, COMPLEX &);

This takes a non-const reference to a COMPLEX object as the second parameter. When you try writing

cout << a + b << endl;

The value of a + b is an rvalue, not an lvalue, because it's the value returned by the function operator +. In C++, you cannot bind a reference to an rvalue, since then you could do Bad Things like this:

COMPLEX& c = a + b; // This step isn't legal
c = 137;            // Wait, what object did we just change?

The problem here is that if we can bind the reference c to the temporary object returned by a + b, then we could use the reference to make changes to that object. But this doesn't make any sense - a + b is the value of an expression, not an actual object.

This is the same problem that's going on here. Your operator << function can't take a + b as a second parameter because a + b is an rvalue.

To fix this, you can change operator << to take const reference to a COMPLEX:

friend ostream& operator<< (ostream& out, const COMPLEX& c);

This works because in C++ you can bind const references to rvalues. The rationale behind this is that if you have a const reference to a temporary, you can't make any changes to that temporary object, so the above example with binding a reference to a + b is no longer a problem.

In general, any overloaded operator that takes in a parameter whose type is another instance of the class that doesn't modify that instance should take its parameter by const reference. This goes for things like operator =, operator +, etc. because it avoids this problem.

OTHER TIPS

Your operator << needs to take a constant reference, otherwise, the compiler will not be able to cast a temporary of type COMPLEX (which results from the addition) into a non-const reference, and might look for an alternative operator << to call.

friend ostream& operator << (ostream &, const COMPLEX &); //notice "const"

To understand the rest of the operator mechanics, you only need to take a look at the operator precedence table.

rewrite your cout statement to

cout << "something" << (complex1 + complex2) << "\n";

Your problem is that operator<< is always called before operator+. The fact that you provide overloads doesn't change this.

On the other hand, you generally shouldn't mix computations an I/O anyway (perhaps only to save some typing), because that makes it hard to see the order of your computations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top