C++联盟,结构,会员类型

C++联盟,结构,会员类型

问题描述:

如果我有一个类:C++联盟,结构,会员类型

class Odp 
{ 
    int i; 
    int b; 
    union 
    { 
     long f; 
     struct 
     { 
       WCHAR* pwszFoo; 
       HRESULT hr; 
     }; 
    }; 

} 

联盟表示,列出的所有价值,就只能采取在上一次的值中的一个?如何在访问这些变量方面发挥作用?我如何直接访问hr?如果我设置hr,如果我尝试访问f会发生什么情况?

这是C++标准中一个非常重要的领域 - 基本上是一个联合实例,根据标准只能在任何时候对待,就好像它包含一个“活动”成员 - 最后一个写入它的成员。所以:

union U { 
    int a; 
    char c; 
}; 

则:

U u; 
u.a = 1; 
int n = u.a; 
u.c = 2; 
char c = u.c; 

是确定的,但:

U u; 
u.a = 1; 
char c = u.c; 

不是。但是,有大量的现有代码表示两者都可以。并且在任何情况下,或者在任何情况下都将引发“无效”访问的例外。 C++语言特别使用例外(!)。

基本上,如果您发现自己在您的C++代码中使用工会来处理除C库之外的任何内容,则会出现问题。

+0

+1 - 但即使对于C库,reinterpret_cast'在大多数情况下都可以使用,而不是联合使用。 – 2010-06-18 21:10:18

它只是意味着您可以访问与long或struct相同的内存。

要访问hr

Odp o1; 
o1.hr; 

有趣链接:http://www.cplusplus.com/forum/general/18816/

+0

在这种情况下,该结构没有名称。我将如何访问它? – 2010-06-18 17:26:39

+1

@Rosarch:从技术上讲,它在C中是非法的。它在C++中是合法的,在这种情况下,这些名字被暴露为“class Odp”的成员。 – 2010-06-18 17:29:43

+0

很好的@Billy – 2010-06-18 17:30:52

右,与union同一存储器位置将被用于表示在任何给定时间的构件中的单独一个。所以如果你有一个联合的实例并且设置了hr的值,那么如果你尝试读取f的值,你将会得到垃圾。

尝试使用下面的访问hr

union a; 
a.hr = NULL; 
+0

所以这是由程序员来防范它,或将引发异常? – 2010-06-18 17:27:35

+0

@Rosarch:这是一个C功能; C没有例外。使用工会需自担风险:) – 2010-06-18 17:29:05

+0

不会抛出异常;这取决于程序员确保他们正在访问'union'的正确成员。 – 2010-06-18 17:31:13

你设定每次(写)工会的会员,你基本上是让“活动”。您只能阅读当前活动的工会成员。这意味着您有责任记住每个时刻哪个成员处于活动状态。

试图访问联合的非活动成员会导致未定义的行为。

请记住,您的代码不是有效的C++。在C++中没有“匿名结构”这样的事情。你的结构成员必须有一个名字。如果您的编译器接受它,它只是您的特定编译器支持的非标准扩展。

+0

嗯......我知道结果会返回未定义的数据,但AFAIK访问其他成员的行为不应该导致像访问空指针的目标这样的未定义行为。 – 2010-06-18 17:31:08

+3

@Billy ONeal:是的,它应该,原因很明显。由于类型通常是不相关的,其他(非活动)成员可能很容易陷入陷阱表示。这是行为未定义的主要原因(也是显而易见的)。 – AnT 2010-06-18 17:34:26

+2

“陷阱表示” 2010-06-18 21:09:25

尝试访问“f”会给你一些结果。它很可能是代表其他联盟成员的数据类型为“f”,即在这种情况下,您很可能会读取部分或全部内容的“pwszFoo”表示为“长”数据类型。一般概念很简单 - 工会成员在记忆*享相同的位置。