开发者

Why can't we overload "=" using friend function?

开发者 https://www.devze.com 2022-12-31 01:19 出处:网络
Why it is not allowed to overload \"=\" using friend function? I have written a small program but it is giving error.

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&)


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


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
//}


Assignment(=) operator is a special operator that will be provided by the constructor to the class when programmer has not provided(overloaded) as member of the class.(like copy constructor).
When programmer is overloading = operator using friend function, two = operations will exists:
1) compiler is providing = operator
2) programmer is providing(overloading) = operator by friend function.
Then simply ambiguity will be created and compiler will gives error. Its compilation error.


There is no good reason for that, I think Stepanov proposed that there should be a free operator= and many good stuff can be done with that (even more than what can be done with the move assignment). I can't find the citation but Stepanov went as a far as to suggest that the constructors could be free functions http://www.stlport.org/resources/StepanovUSA.html.

There is a way around it, which is to systematically declare a template<class Other> A& operator=(Other const& t); in inside all your classes, in this way you leave the option to anyone to define a custom assignment operator.

Of course you can't do this with a class you don't have control over.

Having said that it is nowadays not that bad since we have move assignment. And in some sense conversion operators B::operator A() const{...} are almost like a custom copy assignment. Conversion operators are now usable because of explicit. However you have to have control over the second type (B), the right-hand type in assignment.

Next question is why conversion operator need to be members them selves? Again, I don't think there is a good reason.

0

精彩评论

暂无评论...
验证码 换一张
取 消