C++继承、转让

C++ inheritance, assignment

本文关键字:转让 继承 C++      更新时间:2023-10-16
class Base{ ... } a, b;
class Derived{ ... } c, d;
a = c;  // why does this work?
d = b;  // and why doesn't this work?
d = static_cast<Derived>(b)  // does this actually work?

将基类分配给派生类并反转时究竟会发生什么?

对于类类型,赋值是通过调用函数 operator=() 来完成的。如果您自己不声明,则将为您隐式声明复制赋值运算符;对于您的课程,这些看起来像:

Base::operator=(Base const &);
Derived::operator=(Derived const &);

因此,我们可以从任何Base分配给Base对象,包括派生类型。这就是第一行工作的原因。从派生类赋值(或初始化)有时称为切片:仅复制基子对象,而派生类将被忽略。

我们不能从Base赋值给Derived,因为它的隐式运算符需要一个Derived。这就是第二行不起作用的原因,除非您要声明一个采用Base参数的运算符。

第三行尝试创建一个从b初始化的临时Derived对象,然后将其分配给d。当且仅当Derived有一个转换构造函数采用类型 Base 的参数时,这将起作用。

C++中的公共继承(我假设您已经实现了)关系是"is-a"关系,因此Derived是一个可能更专业的Base

a = c;  // why does this work?

因此,为什么你可以将c分配给a似乎是合理的,因为c是一个Derived,但根据定义也是一个Base

d = b;  // and why doesn't this work?

另一方面,你不能将Base b分配给Derived d,因为d可能有成员,不能由Base的构造函数初始化。

因为Derived是从Base派生出来的,所以Derived是一个Base,只是有额外的功能。因此,可以为Base变量分配一个Derived变量,但是,它将失去Derived方法中引入的额外功能。

颠倒这个逻辑,Derived不是Base,它不止于此,所以你不能反过来分配,因为这会增加功能,而不是删除获得的东西。

至于最后一行,我不确定它是否会编译,但充其量如果它编译了,由于上述原因,您将具有未定义的行为。

请注意,我刚才所说的一些内容在进入虚拟继承时是错误的,但您现在不需要担心这一点。

将派生类的实例分配给基类的实例时,将分配所有基类成员。 a = c;

当您尝试将基类的实例分配给派生类

的实例时,它只会为派生类的成员分配一些未初始化的成员。 d = b; 因此,这是不可能的。