前几天有人在水源C版提出这样一个问题.先是代码如下;
using namespace std;
class Base
... {
public :
Base& operator=(const Base &a)
...{
cout<<"Base ="<<endl;
return *this;
}
} ;
class Devide: public Base
... {
public :
Devide& operator=(const Base& a)
...{
cout<<"Devide ="<<endl;
return *this;
}
} ;
int main()
... {
Devide a,b;
a = b;
return 0;
}
提问的人写下这段代码,原意是想让发生在 a=b上的=运算符重载调用Devide类的operator=. 不料却调用了父类的operator= . 有人提出将Devide& operator=(const Base& a) 改为 Devide& operator=(const Devide& a)后 .问题立刻得到解决. 不过问题继续是:为何原来子类里的OPERATOR=没能将父类中的同名函数覆盖.
对这个问题完整的解答如下:
classname::operator=(classname &)是一个特殊的操作符重载函数,C++标准规定:缺省构造函数,拷贝构造函数,拷贝赋值函数,以及析构函数这四种成员函数被称作特殊的成员函数.当类中没有显示定义这几个函数时,编译器将为类添加这几个函数. 提问者在子类中写下的Devide& operator=(const Base& a) 并没有被编译器承认为是一个合法的拷贝构造函数,因而编译器自行添加了Devide& operator=(const Devide& a),在这个函数里,又调用了父类的拷贝构造函数.这也就解释了提问者提出的第一个问题. 当我们显式的定义了拷贝构造函数后,就不用再到父类里去走一遭了.
另一个问题:OPERATOR=的继承性
这个问题是在网上搜到的;问题代码如下:
额外的注释:C++标准规定:如果派生类中声明的成员与基类的成员同名,那么,基类的成员会被覆盖,哪怕基类的成员与派生类的成员的数据类型和参数个数都完全不同。
... {
public:
int operator=(int a)
...{
return 8;
}
int operator+(int a)
...{
return 9;
}
} ;
class B1 : public A1
... {
public:
int operator-(int a)
...{
return 7;
}
} ;
int main()
... {
B1 v;
cout << (v + 2) << endl; // OK, print 9
cout << (v - 2) << endl; // OK, print 7
cout << (v = 2) << endl; // Error, see below
return 0;
}
VC编译器的错误提示:
error C2679: binary '=' : no operator defined which takes a right-and operand of type 'const int' (or there is no acceptable conversion)
在这个例子中,OPERATOR=并非我们上面提到的拷贝赋值函数.只是普通的对=运算符的重载.问题在于子类并没有继承父类中的这个函数.重载OPERATOR+=,该程序可以成功运行.说明子类继承了OPERATOR+=.为什么+=可以被成功继承而=不行呢.假设OPERATOR=可以被正常继承,而根据我们前面的描述,编译器默默地在子类中添加了B1::operator=(B1 &)这样一个成员.根据C++标准,子类中于父类同一名称的函数,不管参数列表如何不同,都实行覆盖.从而我们继承来的OPERATOR=被编译器自动添加的COPY ASSIGNMENT OPERATOR覆盖了.而+=不存在这样的问题,继承得以正常的进行.