6
struct T
{
    int a;
};

struct C
{
    T& r;
    C(T& v) : r(v) {}
};

struct E : T
{
    T& r;
    E(T const& v) : r(*this), T(v) {}   // ok
};

struct F : C, T // base order doesn't matter here
{
    //F(T const& v) : C(*this), T(v) {}   // error : C::r is not initialized properly
    F(T const& v) : C(*static_cast<T*>(this)), T(v) {}   // ok
    //F(T const& v) : C(static_cast<T&>(*this)), T(v) {}   // ok
};

int main()
{
    T v;
    F f(v);
    f.r.a = 1;
}

イニシャライザリストでこのポインタを使用すると問題が発生する可能性がありますが、これがPODで発生するとは予想していなかったため、明示的なキャストによって簡単に修正できます。これはコンパイラのバグまたは標準関連の問題ですか?

4

4 に答える 4

3

CのベースをでF初期化しようとすると、 ( )の型がとの両方から直接派生する*thisため、コンパイラが生成したコピーコンストラクタCとaを使用して定義するコンストラクタの両方T&が一致します。あなたのキャストはこの曖昧さを解決します。*thisFCT

T&コピーコンストラクターは、どちらも同じように優先されると思っていたので、コピーコンストラクターの方が一致していることに驚いています。コピーコンストラクターが選択された場合、ベースはそれ自体から初期化されます。これにより、参照メンバーが初期化されていない参照(それ自体)から初期化されるため、未定義の動作が発生します。

于 2012-08-07T14:32:17.180 に答える
3

コードがあいまいです。

Cのベースを構築するF場合、コンテキストは直接初期化であるため、13.3.1.3が適用されます。

13.3.1.3コンストラクターによる初期化[over.match.ctor]

直接初期化の場合、候補関数は、初期化されるオブジェクトのクラスのすべてのコンストラクターです。

12.8:8に従って、暗黙的に宣言されたコピーコンストラクタが含まれています。

のコンストラクターの候補は、CパラメーターリストによるC(T &)and(デフォルトのコピーコンストラクター)です。どちらの場合も、参照バインディング(13.3.3.1.4)と、それに続く派生からベースへの変換(13.3.3.1)があり、後者の場合は追加のcv資格調整が行われ、両方の場合で変換の全体的なランクが示されます。 。C(const C &)(F)

CTは両方ともの基本クラスですが、別個のタイプであり、どちらも他方の基本クラスではないためF、13.3.3.2:3または13.3.3.2:4のいずれの句も適用されず、変換シーケンスは区別できません。

実際、gcc-4.5.1は次のコードを拒否します。

prog.cpp: In constructor 'F::F(const T&)':
prog.cpp:20:34: error: call of overloaded 'C(F&)' is ambiguous
prog.cpp:9:5: note: candidates are: C::C(T&)
prog.cpp:7:1: note:                 C::C(const C&)
于 2012-08-07T15:04:40.620 に答える
0
構造体C
{{
    T&r;
    C(T&v):r(v){}
};

構造体E:T
{{
    T&r;
    E(T const&v):r(* this)、T(v){} // ok
};

宣言時に参照を初期化する必要がありますが、ここでは宣言したばかりです。これはC++では許可されていません。

于 2012-08-07T14:34:32.470 に答える
0

1)これを初期化リスト http://msdn.microsoft.com/en-us/library/3c594ae3(v=vs.80).aspxで使用しないでください 。このポインターは、非静的メンバー関数内でのみ有効です。基本クラスの初期化子リストでは使用できません。

基本クラスコンストラクターとクラスメンバーコンストラクターは、このコンストラクターの前に呼び出されます。実際には、未構築のオブジェクトへのポインターを別のコンストラクターに渡しました。これらの他のコンストラクターがメンバーにアクセスするか、これでメンバー関数を呼び出すと、結果は未定義になります。すべての構築が完了するまで、このポインターを使用しないでください。

まもなく:Crが不良ポイターによって初期化されました

于 2012-08-07T14:55:01.993 に答える