1

次のコードの場合:

class Foo{
    int foo;
public:
    Foo() : foo(13) {}
    int getFoo() const { return foo; }
};

union Bar{
    Foo fBar;
    double dBar;
};

これは C++ では完全に合法だと思います。http://en.cppreference.com/w/cpp/language/union#Explanation言います:

2 つの共用体メンバーが標準レイアウト型である場合、任意のコンパイラで共通のサブシーケンスを調べることが明確に定義されています

したがって、gccでこれを行うことができます

Bar bar = { Foo() }

Visual Studio 2008 でこれを試すと、次のエラーが表示されます。

エラー C2620: のメンバーBar::fBarに、union Barユーザー定義のコンストラクターまたは重要な既定のコンストラクターがあります

エラー C2620は次のように述べています。

ユニオン メンバーは、既定のコンストラクターを持つことはできません。

何が起きてる?これは C++ の要件だったのですか? Standard Layout が唯一の要件だと思いましたか? これに対する回避策はありますか?

4

1 に答える 1

2

C++98/03 では、9.5 で規定されている C++ 標準

[...]POD 共用体に、共通の初期シーケンス (9.2) を共有する複数の POD 構造体が含まれている場合、およびこの POD 共用体タイプのオブジェクトに POD 構造体の 1 つが含まれている場合、共通を検査することが許可されます。 POD 構造体メンバーのいずれかの初期シーケンス;[...]

これは C++11 で次のように変更されました。

[...]標準レイアウト共用体に、共通の初期シーケンス (9.2) を共有する複数の標準レイアウト構造体が含まれている場合、およびこの標準レイアウト共用体タイプのオブジェクトに標準レイアウト構造体の 1 つが含まれている場合、それは許可されます。標準レイアウトの構造体メンバーの共通の初期シーケンスを検査する;[...]

したがって、C++11 より前では、POD 型をユニオン内でしか使用できませんでした。つまり、MSVS 2008 では正しいエラーが発生していました。新しいタイプの共用体を使用するには、その変更をサポートする MSVS のバージョンを取得する必要があります。この MSDN の記事から、 Unrestricted unionsのセクションの下に、その変更がバージョン 2015 まで行われなかった ことがわかります。

クラスをPODタイプにアップグレードまたは変更する必要があります

于 2016-10-17T15:11:47.203 に答える