2009-07-28 10 views
0

私はあるクラス(B)が常に第2のクラス(D)に派生することを知っているクラス階層を持っています。 Bのコンストラクタでは、構築全体が完了する前に誰もそれを使用しようとすることがないと確信すれば、thisポインタをD *に静的にキャストすることは安全ですか?私の場合、オブジェクトへの参照をさらに別のクラス(A)に渡したいと思います。建設中にこれをダウンキャストしていますか?

struct A 
{ 
    D & d_; 

    A(D & d) : d_(d) {} 
}; 

struct D; //forward declaration 

struct B 
{ 
    A a; 

    B() : a(std::static_cast<D&>(*this)) {} 
}; 

struct D : public B 
{}; 

このコードは安全ですか?

+0

これは、Bが*常に* Aならば、クラスDがどんな値を追加しているのかという問題を提起します。 – JohnMcG

+0

Bはテンプレートパラメータに基づいてメンバー関数を定義するクラステンプレートです。そのようないくつかのクラステンプレートがあり、テンプレートパラメータに依存するインターフェイスを提供するためにDによって継承されます。 –

答えて

0

@AProgrammer's answerは、static_castが、派生クラスのポインタを基底クラスに渡すことで簡単に回避できることに気付きました。したがって、質問はmember-initializer-listへのポインタthisの有効性につながります。

Iは、C++標準[12.6.2.7]で次のノートを発見:MEM-イニシャライザがコンストラクタの範囲で評価されているので、thisポインタをすることができる:

[式リストmem-initializerで使用して、初期化するオブジェクトを参照してください。 ]

したがって、メンバー初期化子リストでthisを使用することは完全に有効であるので、私は(Dのいかなるメンバーがアクセスされていない限り)提示されたコードが安全であると思います。

2

いいえ、そうではありません。 Dのデータメンバーのコンストラクタはまだ実行されていませんでした。

Dのメンバーは構築されていないため、Dはまだ完全に構築されていないため、技術的にはDへの参照は無効にする必要があります。私はそれがほとんどの実装では問題ではないと思っていますが、それでもなお問題はありません。

私はより良い仕組みを提案したいと思いますが、実際の詳細に「より良い」ことが多いと思います。

+0

私はDがまだ構築されていないことを知っています。そのため、私は建設が終わる前にそのメンバーの誰もアクセスされないと確信しています。 –

+0

イニシャライザリストのこのポインタの妥当性については、使用するのが安全ではないことをどこかに読んで覚えていますが、メンバにアクセスしていない場合でもそれは本当ですか?この質問に答えることができる標準の段落を見つけようとします。 –

+0

明らかに、標準では、 'this'は、構成されているオブジェクトを参照するためにmember-initializer-listで使用できることを明示的に述べています。 –

2

私はそれについて何も見つかりませんでした。安全な状態でコードが安全でない理由を見つけるのは難しいです:

struct B 
{ 
    A a; 

    B(D& d) : a(d) {} 
}; 

struct D : public B 
{ 
    D() : B(*this) {} 
}; 

しかし、私はおそらくまだここに存在するフォームを使用しています。

+0

これはstatic_castを避ける良い方法ですが、イニシャライザリストのこれの妥当性に関する問題はまだあります。 +それを書くよりきれいな方法のために+1。 –

関連する問題