在C ++中,union
可以包含静态成员,就像类的情况一样,它们属于一个类,因此对所有对象都是通用的。
union U
{
long l;
int i;
static long sl;
static int si;
};
int U::si;
long U::sl;
期望存储在同一地址的所有联合静态成员与存储的非静态成员类似是合乎逻辑的。但事实并非如此。一个简单的示例显示静态成员存储在不同的地址下,并且可以包含独立的值。
int main()
{
U u;
u.si = 10;
u.sl = 50;
std::cout << "Non-static members adresses: " << &u.i << " " << &u.l << std::endl;
std::cout << "Static members adresses: " << &u.si << " " << &u.sl << std::endl;
std::cout << "Static members values: " << u.si << " " << u.sl << std::endl;
return 0;
}
输出:
Non-static members adresses: 006FF8EC 006FF8EC
Static members adresses: 00AEB144 00AEB140
Static members values: 10 50
我不明白为什么独立的价值存储留在工会中。我认为这是误导,没有任何意义。不过,在我看来,有理由这样做。 union
静态成员的目的是什么?
你可以从两个角度来看待这个问题。
工会首先是一个阶级。它的目的不同于一个类,但它是通过一个类来了解的。
union是一个类,只有一个子对象在任何一种类型中都处于活动状态。为此,它改变了工会的成员子对象的工作方式。这也是工会不能拥有基类子对象的部分原因。
静态数据成员不是成员子对象,因此它们在联合中的处置应该与它们在非联合类中的处置没有区别。
此外,C ++中的类型的静态成员实际上只是函数和对象名称的作用域机制。它们仍然是有效的全局,但它们可以是私有的和隐藏的,并且它们必须以它们的类型名为前缀,以便您使用它们。
联合的静态数据成员与类的静态数据成员的行为方式完全不同。
联合存在于C中,因此C ++也必须拥有它们。但是工会很难在C ++对象模型中定义,使用起来很痛苦,还有很多其他的东西。因此,您可以将工会视为C ++需要具备但不愿意处理的事物。那你怎么处理它们?
在处理C工会的工作方式时,你使工会像C一样工作。在C中没有这样的东西作为静态成员,因此没有C代码期望静态联合成员被组合。因此......不要将它们结合起来。如果用户真正需要一个静态成员,该成员是某些类型集合的联合,那么他们可以轻松地创建一个联合并创建该类型的单个静态成员。
因此,通过使静态成员不同,用户不会失去任何表现力。
工会是一次最多只能容纳一个数据成员的类[basic.compound]p1.6 [class]p7 [class.union],并且对于他们的静态数据成员w.r.t没有特殊规则。其他类型(即class
和struct
)。
因此,静态数据成员的行为与所有类中的行为相同。
如果你想拥有一个静态数据成员,它是几种类型的联合,你可以这样做:
union U {
long l;
int i;
union {
long l;
int i;
} static s;
};
decltype(U::s) U::s;
// They are the same indeed
static_assert(&U().s.l == &U().s.l);
您需要通过s
引用元素,例如:但是,s.l
而不是sl
。