Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否允许它访问联合成员的公共基类,而不考虑存储的类型?_C++_Unions - Fatal编程技术网

C++ 是否允许它访问联合成员的公共基类,而不考虑存储的类型?

C++ 是否允许它访问联合成员的公共基类,而不考虑存储的类型?,c++,unions,C++,Unions,考虑一个成员共享公共基类的联合: struct Base { int common; }; struct DerivedA : Base {}; struct DerivedB : Base {}; union Union { DerivedA a; DerivedB b; }; 无论联合在运行时“包含”了什么(即,最后存储的值是什么),只要它包含了某个东西,该东西就是Base的子类。那么,是否有任何方法可以合法地使用这个想法来访问Base字段,而不知道存储在uni

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

struct Base {
    int common;
};

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

union Union {
    DerivedA a;
    DerivedB b;
};
无论联合在运行时“包含”了什么(即,最后存储的值是什么),只要它包含了某个东西,该东西就是
Base
的子类。那么,是否有任何方法可以合法地使用这个想法来访问
Base
字段,而不知道存储在union中的对象的实际类型

可能是这样的:

Base* p = reinterpret_cast<Base*>(&u);
Base*p=重新解释铸件(&u);
。。。可能不会。也许是这样:

Base* p2 = static_cast<Base *>(&u.a);
Base*p2=static_cast(&u.a);
如果
u.b
是最后一个存储值,是否合法

我知道有一些关于“公共初始序列”的特殊规则适用于并集,但不清楚基类是否也有类似的规则


显然,它对多重继承不起作用,所以这可能表明它根本不起作用。

通过包含基类的任何成员访问基类是合法的,前提是所使用的结构是标准布局


在您提供的示例中,结构是标准布局,因此您可以通过
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.
)

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


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

“标准布局类是一个具有相同访问控制的类(第11条)对于所有非静态数据成员…要么在最派生的类中没有非静态数据成员,要么最多有一个基类具有非静态数据成员,要么没有基类具有非静态数据成员…”如问题所示,
DerivedA
DerivedB
是布局兼容的。但一旦派生类具有非静态数据成员,它们就不再与布局兼容。但是基类是,所以。。。不确定。此上下文中的“成员”(例如,在包括继承成员在内的所有非静态成员中,首先在同一类中声明)是否仅指数据成员(字段)或成员函数?