我看到了一些代码如下:
class A
{
private:
union {
B *rep;
A *next;
}; // no variables of this anonymous defined!
void func()
{
A *p = new A;
p->next = NULL; // why p has a member variable of 'next'?
}
};
我已经用VS2010编译了上面的代码而没有任何错误。 这是问题,
为什么p有成员变量'next'?
union {
B *rep;
A *next;
};
据我所知,这是一个匿名联盟,甚至没有定义变量。我们如何才能像这样访问这个联合中的成员变量?
答案 0 :(得分:19)
因为这几乎就是一个匿名联盟所做的事情,它在封闭命名空间(在类声明中使它们成为字段名称)中定义了零或多个变量,这些变量占用了重叠的内存。因此,在使用它时,就像你宣布
一样class A
{
private:
B *rep;
A *next;
void func()
{
A *p = new A;
p->next = NULL;
}
};
...除了rep和next占用重叠空间(或者假设两个指针具有相同的大小,相同的空间),因此命名联合带来的所有危险和好处。
答案 1 :(得分:12)
以下是控制此行为的标准引用:第[class.union]
部分(来自C ++ 0x草案n3242的措辞)
表格的联合
union {
member-specification} ;
被称为匿名联盟;它定义了一个未命名类型的未命名对象。匿名联合的成员规范应仅定义非静态数据成员。 [注意:嵌套类型和函数不能在匿名联合中声明。 - 尾注]匿名工会成员的名称应与宣布匿名工会的范围内的任何其他实体的名称不同。出于名称查找的目的,在匿名联合定义之后,匿名联合的成员被认为是在声明匿名联合的范围内定义的。
答案 2 :(得分:0)
我不确定我理解你的问题。
A有成员p,因为你在匿名联盟内的A中声明了它与rep。
你确实声明了一个变量!只是'rep'和'next'共享相同的内存。
您可以按照自己的方式访问它。
匿名联合(就像结构一样)将它们的成员放在与上述命名空间相同的命名空间中。
这对于例如:
是有用的union W00t {
struct {
uint32_t a,b;
};
struct {
uint64_t c;
};
}
答案 3 :(得分:0)
我很惊讶有一个现代编译器仍然允许该构造。它起源于C的早期,大约1975年。在那些日子里,结构和联合成员实际上并没有绑定到特定的结构,而是作为属性包含与基址和数据类型的偏移。
最终结果是正确使用结构或联合会产生正确的代码,其表达式按预期进行评估。唯一的区别是,使用与该类型无关的指针滥用结构成员不会被标记为错误。我认为没有任何特殊原因可以不强制执行员工K& R暗示未来的编译器希望会检查这样的用途 - 可能只是为了保存16位域中的符号表空间。 / p>