构造函数、析构函数、赋值操作符都是不能被继承的。其中赋值操作符有一些有趣的特征:
如果编译器发现程序将一个对象赋给同一个类的另一个对象,它将自动为这个类提供一个赋值操作符。这个操作符的默认或隐式版本将采用成员赋值,即将原对象的相应成员赋给目标对象的每个成员。
不过,如果对象属于派生类,编译器将使用基类赋值操作符来处理派生对象中基类部分的赋值。如果显示地为基类提供了赋值操作符,将使用该操作符。与此相似,如果成员是另一个类的对象,则对于该成员,将使用其所属类的赋值操作符。
当基类和派生类都定义了赋值操作符时,将派生类对象赋给基类对象:
class_a A; //base class
class_b B("type",100,200,0); //derived class
A=B; // assign derived object to base object
赋值语句将被转换成左边的对象调用的一个方法:
A.operator=(B);
因此它将调用class_a::operator=(const class_a &)函数。is-a关系允许基类引用指向派生类对象。该赋值操作符只处理基类成员,将忽略派生类的新增成员。
如果将基类对象赋给派生类对象:
class_a A("type",100); //base class
class_b B; //derived class
B=A; // possible?
上述赋值语句将被转换为:
B.operator=(A);
因此它将调用class_b::operator=(const class_b &)函数。不过,派生类引用将不能自动引用基类对象,所以上述代码不能运行,除非有下面的转换构造函数:
class_b(const class_a &);
如果有转换构造函数,程序将通过它根据(A)来创建一个临时class_b对象,然后将它用于赋值操作符的参数。
另一种方法是,定义一个用于将基类赋给派生类的赋值操作符:
class_b & class_b::operator= (const class_a &){...}
如果既没有转换构造函数,也没有重载赋值操作符,则不能这样做,除非使用显示强制类型转换。