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
似乎是合理的,因为 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
,它不止于此,因此您不能以相反的方式分配,因为那样会增加功能,而不是删除原来的功能获得了。
至于最后一行,我不确定它是否会编译,但充其量如果能编译,由于上述原因,您将有未定义的行为。
请注意,在进入虚拟继承时,我刚才所说的某些内容是错误的,但您现在无需担心。
当您将派生 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
.
的参数时,这才有效
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
似乎是合理的,因为 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
,它不止于此,因此您不能以相反的方式分配,因为那样会增加功能,而不是删除原来的功能获得了。
至于最后一行,我不确定它是否会编译,但充其量如果能编译,由于上述原因,您将有未定义的行为。
请注意,在进入虚拟继承时,我刚才所说的某些内容是错误的,但您现在无需担心。
当您将派生 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
.