考虑一个联合,其成员共享一个公共基类:
struct Base {
int common;
};
struct DerivedA : Base {};
struct DerivedB : Base {};
union Union {
DerivedA a;
DerivedB b;
};
无论联合体在运行时“包含”什么(即最后存储的值是什么),只要它包含某些内容,该内容就是该内容的子类Base
。那么有没有什么方法可以合法地使用这个想法来访问Base
字段,而不知道联合中存储的对象的实际类型?
也许是这样的:
Base* p = reinterpret_cast<Base*>(&u);
... 可能不会。也许这个:
Base* p2 = static_cast<Base *>(&u.a);
是否合法,如果u.b
是最后一次存储的值吗?
我知道有关于适用于联合的“公共初始序列”的特殊规则,但尚不清楚基类是否有类似的规则。
显然它不适用于多重继承,所以也许这表明它根本不起作用。
您输入的示例实际上是有效的,但它不允许进行许多有用的更改。
联合非活动成员的任何部分上唯一有效的左值到右值转换是使用活动成员 ([class.mem]/23) 访问该成员的公共初始序列的一部分。
但公共初始序列仅为两个标准布局结构体 ([class.mem]/20) 定义,并且对于标准布局结构体 ([class]/7) 的资格有相当多的规则。总结:
该类可能不是多态的。
一个类不能有多个相同类型的基类。
该类可能没有引用类型的非静态成员。
类的所有非静态成员都具有相同的访问控制。
所有非静态成员(包括继承成员)首先在同一个类中声明。
所有基类和非静态成员(包括继承成员)都递归地遵守上述所有规则。
有些规则规定标准布局结构的第一个非静态成员与结构具有相同的地址,并且标准布局联合的所有非静态成员具有相同的联合地址。但是,如果这些规则的任何组合都意味着相同类型的两个对象必须具有相同的地址,则包含的结构/联合不是标准布局。
(最后一条规则的示例:
struct A {}; // Standard-layout
struct B { A a; }; // Standard-layout (and &b==&b.a)
union U { A a; B b; }; // Not standard-layout: &u.a==&u.b.a ??
struct C { U u; }; // Not standard-layout: U is not.
)
Your DerivedA
and DerivedB
都是标准布局,因此允许它们具有共同的初始序列。事实上,该共同序列是单一的int
每个的成员,因此它们实际上是完全布局兼容的(因此可以是包含这两个结构的其他一对结构的公共初始序列的一部分)。
然而,这里更棘手的事情之一是关于属于同一类的所有成员的规则。如果您添加任何非静态成员DerivedA
and/or DerivedB
,即使您向两者添加相同类型的成员,更改后的结构也不再是标准布局,因此不存在共同的初始序列。这限制了您想要在此模式中使用继承的大多数现实原因。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)