tags:

views:

332

answers:

2

Why it is not allowed to overload "=" using friend function? I have written a small program but it is giving error.

class comp
{
int real;
int imaginary;
public:
comp(){real=0; imaginary=0;}
void show(){cout << "Real="<<real<<" Imaginary="<<imaginary<<endl;}
void set(int i,int j){real=i;imaginary=j;}
friend comp operator=(comp &op1,const comp &op2);
};

comp operator=(comp &op1,const comp &op2)
{
op1.imaginary=op2.imaginary;
op1.real=op2.real;
return op1;
}

int main()
{
comp a,b;
a.set(10,20);
b=a;
b.show();
return 0;
}

The compilation gives the following error :-

[root@dogmatix stackoverflow]# g++ prog4.cpp 
prog4.cpp:11: error: ‘comp operator=(comp&, const comp&)’ must be a nonstatic member function
prog4.cpp:14: error: ‘comp operator=(comp&, const comp&)’ must be a nonstatic member function
prog4.cpp: In function ‘int main()’:
prog4.cpp:25: error: ambiguous overload for ‘operator=’ in ‘b = a’
prog4.cpp:4: note: candidates are: comp& comp::operator=(const comp&)
prog4.cpp:14: note:                 comp operator=(comp&, const comp&)
+8  A: 

Because if you do not declare it as a class member compiler will make one up for you and it will introduce ambiguity.

Michael Krelin - hacker
What is the signature for that overloaded "=" operator which compiler introduces automatically?
Ashish
Same as yours but the return value is a reference.
ur
Michael Krelin - hacker
ur, it couldn't be the same, because it only takes one parameter.
Michael Krelin - hacker
I think this answer is true, and I think it best explains what the compiler is doing and asking for (which is very important), but I don't think it explains why you shouldn't write the operator=() the way ashish-sangwan did in theory.
sheepsimulator
sheepsimulator, *in theory* you would be able to write it if not the reason stated above. Just think of the `operator+=()` that you can actually overload to do exactly what `operator=()` is supposed to do and implement it outside of the class. And I hate to talk about why people *SHOULD NOT* do things. They shouldn't do anything without understanding and if they understand there's nothing that should stop them from doing weird things.
Michael Krelin - hacker
Johannes Schaub - litb
Thanks for elaborating on that, litb!
Michael Krelin - hacker
+2  A: 

The assignment operator is explicitly required to be a class member operator. That is a sufficient reason for the compiler to fail to compile your code. Assignment is one of the special member functions defined in the standard (like the copy constructor) that will be generated by the compiler if you do not provide your own.

Unlike other operations that can be understood as external to the left hand side operator, the assignment is an operation that is semantically bound to the left hand side: modify this instance to be equal to the right hand side instance (by some definition of equal), so it makes sense to have it as an operation of the class and not an external operation. On the other hand, other operators as addition are not bound to a particular instance: is a+b an operation of a or b or none of them? -- a and b are used in the operation, but the operation acts on the result value that is returned.

That approach is actually recommended and used: define operator+= (that applies to the instance) as a member function, and then implement operator+ as a free function that operates on the result:

struct example {
   example& operator+=( const example& rhs );
};
example operator+( const example& lhs, const example& rhs ) {
   example ret( lhs );
   ret += rhs;
   return ret;
}
// usually implemented as:
// example operator+( example lhs, const example& rhs ) {
//    return lhs += rhs; // note that lhs is actually a copy, not the real lhs
//}
David Rodríguez - dribeas
Your reasons aren't valid, because `operator=()` is not any more bound to the target instance than `operator+=()`, which *can* be defined outside class, because compiler will not interfere and introduce ambiguity.
Michael Krelin - hacker
I did not say that the semantics is what made the distinction, or else, as you state, all `operatorX=` would have to be member functions. The reason why it cannot be a free function is in the first paragraph: because the standard says so. I guess I was not clear --english is not my mother tongue -- I just meant to state that from the semantic point of view it makes more sense to have `operatorX=` (including `operator=`) as member functions even if `operatorX` is usually better implemented as a free function.
David Rodríguez - dribeas
I guess the question was really why standard says so ;-)
Michael Krelin - hacker
There are some other quirks like that, why does `operator[]` have to be a member function? Why must `operator->` be member but `operator->*` can be implemented as a free function?
David Rodríguez - dribeas