2010-06-18 81 views
3

如果我有一個類:C++聯盟,結構,會員類型

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

} 

聯盟表示,列出的所有價值,就只能採取在上一次的值中的一個?如何在訪問這些變量方面發揮作用?我如何直接訪問hr?如果我設置hr,如果我嘗試訪問f會發生什麼情況?

回答

7

這是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

1

它只是意味着您可以訪問與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

1

右,與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

3

你設定每次(寫)工會的會員,你基本上是讓「活動」。您只能閱讀當前活動的工會成員。這意味着您有責任記住每個時刻哪個成員處於活動狀態。

試圖訪問聯合的非活動成員會導致未定義的行爲。

請記住,您的代碼不是有效的C++。在C++中沒有「匿名結構」這樣的事情。你的結構成員必須有一個名字。如果您的編譯器接受它,它只是您的特定編譯器支持的非標準擴展。

+0

嗯......我知道結果會返回未定義的數據,但AFAIK訪問其他成員的行爲不應該導致像訪問空指針的目標這樣的未定義行爲。 – 2010-06-18 17:31:08

+3

@Billy ONeal:是的,它應該,原因很明顯。由於類型通常是不相關的,其他(非活動)成員可能很容易陷入陷阱表示。這是行爲未定義的主要原因(也是顯而易見的)。 – AnT 2010-06-18 17:34:26

+2

「陷阱表示」< - 之前從未聽說過那個。 +1 – 2010-06-18 21:09:25

0

嘗試訪問「f」會給你一些結果。它很可能是代表其他聯盟成員的數據類型爲「f」,即在這種情況下,您很可能會讀取部分或全部內容的「pwszFoo」表示爲「長」數據類型。一般概念很簡單 - 工會成員在記憶中共享相同的位置。