2012-10-24 133 views
6

我很驚訝這不起作用:我可以初始化mem初始化程序中的聯合?

union DlDatum 
{ 
    float mFloat; 
    s32 mInteger; 
}; 

class DlDbE 
{ 
public: 
    DlDbE(float f) : mData.mFloat(f) {}; 
private: 
    DlDatum mData; 
}; 

有沒有辦法在一個C++構造MEM-初始化列表來初始化工會?

更新:答案是爲聯合創建構造函數。不知道可以做到。下面是我做的:

union DlDatum 
{ 
    float mFloat; 
    s32 mInteger; 
    bool mBoolean; 
    u32 mSymbol; 
    u32 mObjIdx; 

    DlDatum(  ) : mInteger(0) {} 
    DlDatum(float f) : mFloat(f) {} 
    DlDatum(s32 i) : mInteger(i) {} 
    DlDatum(bool b) : mBoolean(b) {} 
    DlDatum(u32 s) : mSymbol(s) {} // this ctor should work for objIdx also 
}; 

class DlDbE 
{ 
public: 
    DlDbE() {} 
    DlDbE(float f) : mData(f) {} 
    DlDbE(u32 i ) : mData(i) {} 
    DlDbE(bool b ) : mData(b) {} 
    ...etc.. 
private: 
    DlDatum mData; 
}; 
+0

http://stackoverflow.com/questions/321351/initializing-a-union-with-a-non-trivial-constructor – Mysticial

回答

11

像任何其他成員,如果你想建立一個聯盟,你將不得不放棄工會一個構造函數和調用。

+0

不知道工會可以有構造函數。我會嘗試的。他們可以有會員嗎? –

+0

@RafaelBaptista是的,只是沒有虛擬功能。他們也不能從任何東西繼承或繼承。 –

+0

有趣。像gimped類。 –

9

在C++ 03中以及在限制爲聯合編寫構造函數之前。

在C++ 11中統一初始化擴展了集合初始化到構造函數初始化列表的語法。這意味着,像

DlDatum d = { 3.0 }; 

,我們都知道,並在C愛和美好的舊聚集初始化語法初始化聯合的第一個成員,現在可以在構造函數初始化列表中使用以及

union DlDatum 
{ 
    float mFloat; 
    s32 mInteger; 
}; 

class DlDbE 
{ 
public: 
    DlDbE(float f) : mData{f} {} 
private: 
    DlDatum mData; 
}; 

此功能只允許您「聯合」聯盟的第一個非靜態成員進行初始化。如果你需要更靈活的東西,那麼它回到編寫構造函數。

1

@AndreyT給出了一個很好的答案,我會用一些實際的建議來擴展。

我傾向於使用工會,以便輕鬆訪問位圖值,而不需要繁瑣和醜陋的按位和/或按位或。我認爲這是一個相當普遍的做法。我已經使用了一段時間

一種技術,使工藝更簡單是如果我用不到32位的位圖工作我宣佈它作爲一個無名結構一個聯合內與同伴DWORD沿數據成員。例如:

union UNICODECONTROL{ 
    DWORD   dwAccessor; 
    struct{ 
     unsigned unicode_01 : 1; 
     unsigned unicode_02 : 1; 
     unsigned unicode_03 : 1; 
     unsigned unicode_04 : 1; 
     unsigned unicode_05 : 1; 
     unsigned unicode_06 : 1; 
     unsigned unicode_07 : 1; 
     unsigned unicode_08 : 1; 
     unsigned unicode_09 : 1; 
     unsigned unicode_10 : 1; 
    }; 
}; 

有了它,它就像'訪問器'功能一樣工作。如果您想設置值,您可以通過爲該「訪問者」指定一個具有適當位圖的數字來完成此操作。你想把它們都歸零 - 也是一塊蛋糕。它特別適用於Windows註冊表。爲了存儲聯合位圖的值,您只需將DWORD寫入註冊表!稍後重新進行重新初始化也同樣簡單。

A DWORD是註冊表的本機類型之一,你不需要搞亂靜態轉換或編寫手動轉換函數。如果您的位圖長度超過32位,則可以聲明一個64位大小的整數,並且它的工作方式與通常情況相同 - 同樣適用於註冊表,作爲QUADWORD也是本機類型。

這直接影響到@AndreyT提到的內容 - 如果您想在我的聯合位圖/格式中方便地初始化類數據成員,那麼您所要做的就是 - 像在示例中一樣 - 確保'訪問者'是聯盟中聲明的第一個值。然後,您可以使用新的C++ 11'{}'方案直接記憶它。根本不需要奇怪的聯合構造函數!

一個告誡。如果單獨的位圖位在「內部」存取器DWORD中,將取決於結構的對齊設置。這是在編譯器級別設置的,或者使用MSVC++中的__declspec(align(#))語句和其他編譯器中的類似語法設置。

最後,在最近嘗試將這些想法用於幾種不同場景時學到的更新。儘管事實上C++ 11明確表示如上所述通過它的第一個變量初始化一個聯合是合法的,但MSVC++似乎忽略了這個標準 - 或者''作爲編譯器錯誤輸出指出它沒有實現。因此,如果您使用的是Microsoft編譯器,如果要初始化它,則必須爲您的聯合實現一個混亂的構造函數。令人遺憾的是,對於VS2013以及整個IDE的下一個2014版本,推測符合C++ 11標準將會進一步改進。