一、将派生类对象赋值给基类对象?
注意:这不同于将派生类对象赋值给基类的引用或者指针
请看如下代码:
Base b; //基类对象
Derived d; //派生类对象
b=d; //赋值
这将使用哪一个运算符呢?赋值语句实际上会被转换为下面的语句:
b.operator=(d);
其中左边的对象是基类对象,所以调用的是基类中的赋值运算符重载函数,右边的对象作为传入的参数。而实参与形参结合的过程实际上就是派生类对象赋值给基类对象的引用。所以,b=d
实际上就是将d
中的基类成员赋值给了b
,而忽略了d
中新增加的成员。总之,派生类对象可以赋值给基类对象,但是只涉及到基类中的成员。
二、将基类对象赋值给派生类对象?
Base b; //基类对象
Derived d; //派生类对象
d=b; //赋值
赋值语句会被转换为下面的语句:
d.operator=(b);
左边的对象是派生类对象,所以会调用派生类中的赋值运算符重载函数,右边的对象会作为实参传入。但是C++中基类对象不能自动的转换为派生类对象的引用,因此这样的代码是不能运行的。那么我们应该怎样解决这样的问题呢?
解决办法一:
在派生类中定义一个转换构造函数(这个之前我已经写过一篇关于它的博客),如下:
Derived(const Base& ba)
该转换构造函数可以将Base
类型转换为Derived
。当我们定义了一个如此的转换构造函数之后,当实参与形参结合时,发现实参是一个Base
类型与形参不符,此时因为类中有相应的转换构造函数,所以此时就会调用该函数,程序就会用b
去构造一个临时的
Derived
对象,然后再用该临时对象作为赋值运算符的实参。
解决办法二:
在派生类中以基类对象作为形参再新定义一个赋值运算符重载函数,如下:
Derived& operator=(const Base& ba); //此时的形参是基类的引用
这样赋值运算符的类型相匹配,无需进行其他操作。
总而言之,问题”基类对象能否赋值给派生类对象”的答案是可能可以。只有有上面所述的两个解决办法中的任意一个时,就可以进行赋值,否则是不可以的。