无论存储类型如何,是否都允许访问联合成员的公共基类? [英] Is it allowed to access a common base class of union members regardless of the stored type?

查看:40
本文介绍了无论存储类型如何,是否都允许访问联合成员的公共基类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个成员共享一个公共基类的联合:

Consider a union whose members share a common base class:

struct Base {
    int common;
};

struct DerivedA : Base {};
struct DerivedB : Base {};

union Union {
    DerivedA a;
    DerivedB b;
};

无论联合在运行时包含"什么(即最后存储的值是什么),只要它包含某些东西,该东西就是 Base 的子类.那么有没有什么办法可以合法地使用这个想法来访问Base字段,而无需知道联合中存储的对象的实际类型?

No matter what the union "contains" at runtime (i.e., what the last stored value was), as long as it contains something, that something is subclass of Base. Is there then any way to legally use this idea to access the Base field, without knowing the actual type of the object stored in the union?

也许是这样的:

Base* p = reinterpret_cast<Base*>(&u);

...可能不是.也许是这样:

... probably not. Maybe this:

Base* p2 = static_cast<Base *>(&u.a);

如果 u.b 是最后存储的值是否合法?

Is it legal if u.b was the last stored value?

我知道有关于适用于联合的公共初始序列"的特殊规则,但不清楚基类是否有类似的规则.

I know there are special rules about "common initial sequences" that apply for unions, but it isn't clear if there is something similar for base classes.

显然它不适用于多重继承,所以也许这表明它根本不起作用.

Clearly it won't work for multiple inheritance, so maybe that's an indication it won't work at all.

推荐答案

您输入的示例实际上是有效的,但它不允许进行许多有用的更改.

Your example exactly as you typed it is in fact valid, but it doesn't allow for many useful changes.

对联合的非活动成员的任何部分进行的唯一有效的左值到右值转换是访问该成员与活动成员的公共初始序列的一部分 ([class.mem]/23).

The only valid lvalue-to-rvalue conversion on any part of an inactive member of a union is to access a part of that member's common initial sequence with the active member ([class.mem]/23).

但是共同的初始序列只为两个标准布局结构体([class.mem]/20)定义,对于什么是标准布局结构体([class]/7),有很多规则.总结:

But the common initial sequence is only defined for two standard-layout structs ([class.mem]/20), and there are quite a few rules for what qualifies as a standard-layout struct ([class]/7). Summarizing:

  • 该类不能是多态的.

  • The class may not be polymorphic.

该类不能有多个相同类型的基类.

The class may not have more than one base class with the same type.

该类可能没有引用类型的非静态成员.

The class may not have a non-static member of reference type.

该类的所有非静态成员都具有相同的访问控制.

All non-static members of the class have the same access control.

包括继承成员在内的所有非静态成员首先在同一个类中声明.

All non-static members including inherited members are first declared in the same class.

包括继承成员在内的所有基类和非静态成员递归地遵守上述所有规则.

All base classes and non-static members including inherited members obey all the above rules, recursively.

有规则说标准布局结构的第一个非静态成员与结构具有相同的地址,并且标准布局联合的所有非静态成员具有相同的地址联盟.但是,如果这些规则的任何组合意味着相同类型的两个对象必须具有相同的地址,则包含的结构/联合不是标准布局.

There are rules that say the first non-static member of a standard-layout struct has the same address as the struct, and that all non-static members of a standard-layout union have the same address of the union. But if any combination of these rules would imply that two objects of the same type must have the same address, the containing struct/union is not standard-layout.

(以最后一条规则为例:

(For an example of this last rule:

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.

)

您的 DerivedADerivedB 都是标准布局,因此允许它们具有共同的初始序列.事实上,该公共序列是每个成员的单个 int 成员,因此它们实际上是完全布局兼容的(因此可能是其他一些包含这两个结构的结构对的公共初始序列的一部分).

Your DerivedA and DerivedB are both standard-layout, so they are permitted to have a common initial sequence. In fact, that common sequence is the single int member of each, so they are in fact fully layout-compatible (and could therefore be part of a common initial sequence of some other pair of structs containing the two).

不过,这里比较棘手的事情之一是关于属于同一类的所有成员的规则.如果您向 DerivedA 和/或 DerivedB 添加任何非静态成员,即使您向两者添加相同类型的成员,更改后的结构是/根本不再是标准布局,因此没有共同的初始序列.这限制了您希望在此模式中使用继承的大多数现实原因.

One of the trickier things here, though, is the rule about all members belonging to the same class. If you add any non-static member to DerivedA and/or DerivedB, even if you add a member of the same type to both, the changed struct(s) is/are no longer standard-layout at all, so there is no common initial sequence. This limits most of the realistic reasons you would have wanted to use inheritance in this pattern.

这篇关于无论存储类型如何,是否都允许访问联合成员的公共基类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆