2012-10-24 5 views
6

私は、これは動作しません驚いている:mem-initializerで共用体を初期化できますか?

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

興味深い。忘れられたクラスのように。 –

9

C++ 03以前では、あなたのユニオンのコンストラクタを書くことに限定されています。

C++ 11の場合一様な初期化コンストラクタ初期化子リストへの集約初期化の構文を拡張しています。これは、我々はすべて知っているし、Cからの愛と

DlDatum d = { 3.0 }; 

のような古き良き集計初期化子の構文は、組合の最初のメンバーを初期化することを意味し、今

union DlDatum 
{ 
    float mFloat; 
    s32 mInteger; 
}; 

class DlDbE 
{ 
public: 
    DlDbE(float f) : mData{f} {} 
private: 
    DlDatum mData; 
}; 
だけでなく、コンストラクタの初期化子リストで使用することができます

この機能では、初期化のためにユニオンの最初の非スタティックメンバーを「対象」にすることができます。より柔軟なものが必要な場合は、コンストラクタの作成に戻ります。

1

@AndreyTは、実用的な助言を借りて、私がさらに拡張する素晴らしい答えを与えます。

ビットマップ値に簡単にアクセスできるようにするために、ユニオンを使用する傾向があります。私はこれがかなり一般的な方法だと思う。私は仲間DWORDとともに組合内部の無名の構造体としてそれを宣言する32ビット未満のビットマップで働いている場合、私は、プロセスをさらに容易にするために、しばらくの間使用してきた

一つの技術はありますデータメンバー。例:

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をレジストリに書き込んでください。再初期化のために後でそれを取り出すことは、同様に簡単です。

DWORDは、レジストリのネイティブタイプの1つで、静的キャストまたは手動変換機能の書き換えを回避する必要はありません。 32ビットよりも長いビットマップの場合は、64ビットサイズの整数を宣言することができ、一般的に同じ方法で動作します。QUADWORDも同様にネイティブタイプです。これは言及@AndreyTものに直接負担し

- あなたは私の組合ビットマップ/ DWORD形式でクラスのデータ・メンバーの便利な初期化をしたい場合、あなたがしなければならないすべては - 例のように - ことを確認してください'アクセサ'は、ユニオンで宣言された最初の値です。次に、新しいC++ 11 '{}'体系で直接mem-listすることができます。奇妙な組合生成者の必要は全くありません!

警告です。別のビットマップビットが「内側」にある場合、アクセサDWORDは構造体の配置設定に依存します。これは、MSVC++のコンパイラレベルまたは__declspec(align(#))ステートメントと他のコンパイラの同様の構文で設定されます。

最後に、これらのアイデアをいくつかの異なるシナリオで最近試してみる間に更新プログラムが学習されました。上記のように、最初の変数でユニオンを初期化することはC++ 11が明示しているにもかかわらず、MSVC++はこの標準を無視しているようです。つまり、は実装されていません。 'したがって、Microsoftコンパイラを使用している場合、初期化したい場合は、union用の乱雑なコンストラクタを実装する必要があります。残念ですが、おそらくC++ 11標準への準拠は、VS2013への今後のサービスパックや、IDE全体の次の2014年の反復で改善されるでしょう。

関連する問題