C++继承、赋值

C++ inheritance, assignment

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?

将基数 class 分配给派生的 class 并反转时究竟发生了什么?

C++ 中的 public 继承(我假设你已经实现)关系是一个 'is-a' 关系,所以 Derived 是一个 Base 可能更多专业化。

a = c;  // why does this work?

所以您可以将 c 分配给 a 似乎是合理的,因为 cDerived,但根据定义也是 Base

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

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

由于 Derived 派生自 BaseDerived 一个 Base,只是具有附加功能。因此,可以为 Base 变量分配一个 Derived 变量,但是,它将失去在 Derived 方法中引入的额外功能。

颠倒逻辑,Derived 不是 Base,它不止于此,因此您不能以相反的方式分配,因为那样会增加功能,而不是删除原来的功能获得了。

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

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

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

当您尝试将基 class 的实例分配给派生 class 的实例时,它只会分配派生 class 的一些成员未初始化。 d = b; 所以这是不可能的。

对于 class 类型,赋值是通过调用函数 operator=() 完成的。如果您不自己声明,那么将为您隐式声明一个 copy-assignment 运算符;对于您的 classes,这些看起来像:

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

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

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

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

的参数时,这才有效