2011-02-02 7 views
17

Herb Sutterは、コンストラクターがcompletees.ieを実行して、最終的な方法でコントロールを最終的なブレースに渡す場合にのみ、オブジェクトが構築された(有効な存在を持つ)アーティクルの1つを示します。コンストラクターでメソッドを呼び出す

今ハーブが言うから

class A 
{ 
    public: 
    A() 
    { 
     f(); 
    } 

    void f() 
    { 
     cout << "hello, world"; 
    } 

}; 

int main() 
{ 
    A a; 
} 

ここで、次のコードを検討し、我々はAが完全に()コンストラクタを呼び出すF内に構築されていないため、コンストラクタの内部では、「このように無効であると言うことはできません"ptrはまだ準備ができていません。

実際には、コンストラクタ内に有効な「this」があり、f()が呼び出されます。

私はハーブが間違ったことを言っているとは思っていませんが、間違って解釈していると思います。

ここに記事へのリンクがあります:http://www.gotw.ca/gotw/066.htm コンストラクタからの例外について説明しています。具体的にはここに私の質問に基づいてそれから抽出されます:

- オブジェクトの生涯は始まるのですか? コンストラクタが正常に完了し、通常を返します。つまり、コントロールはコンストラクター本体の末尾または以前のreturnステートメントに到達します。

-オブジェクトの寿命が終わるのはいつですか? デストラクタが開始されるとき。つまり、コントロールはデストラクタ本体の先頭に到達します。 ここでの重要な点は、オブジェクトの存続期間が始まる前の状態が、オブジェクトの存続期間終了後とまったく同じであることです。期間はです。この観察は重要な問題に私たちをもたらします:

次のように私たちは、C++のコンストラクタモデルをまとめるかもしれません:

Either: 

(a) The constructor returns normally by reaching its end or a return statement, and the object exists. 

Or: 

(b) The constructor exits by emitting an exception, and the object not only does not now exist, but never existed. 

答えて

15

ハーブが言うから、私たちはAが完全でないためという を言うことができません コンストラクタの内部に構築されました コンストラクタ内でf()を呼び出すと、 が無効になりました。この「ptr」はまだ準備ができていません です。 f()virtualclass Aの方法やその継承階層であり、あなたが右の目的に応じf()のランタイム解決を期待する場合にのみです

。簡単に言えば、メソッドがコンストラクタ内で呼び出された場合、virtualメカニズムは起動しません。

f()が仮想関数でない場合、正確にf()が何であるかを知っていれば、コンストラクターから呼び出しても問題ありません。プログラマは通常、コンストラクタからinitialize()のようなクラスメソッドを呼び出します。

ハーブ・サッターの記事へのリンクを教えてもらえますか?

+7

だ場合は、「あなたが慎重にハーブサッターの記事を読んでいないようです。」 - あなたはまだ記事に手を置くことができないと考えて少し厳しいです... – razlebe

+0

@sgreeve:厳しい?どうして? – Nawaz

+3

OPが記事を慎重に読んでいないと仮定しています。記事を見ることなく、あなたは状況をよく説明したかどうかは分かりません。 – razlebe

8

プログラムフローがコンストラクタに入るまでに、オブジェクトのメモリが割り当てられており、実際にはthisポインタが有効です。

ハーブとは、オブジェクトの状態が完全に初期化されていない可能性があるということです。特に、Aから派生したクラスを構築している場合、Aのコンストラクタ内にまだある間は、そのクラスのコンストラクタは呼び出されません。

仮想メンバ関数を使用する場合、Aのコンストラクタ内から呼び出された場合、派生クラスの仮想関数は実行されないため、これは重要です。

0

まだ初期化されていないメンバー変数に注意してください。仮想関数に注意してください。関数が仮想であり、派生オブジェクトが作成されている場合は、呼び出す関数が期待する関数ではない可能性があります。それ以外では、コンストラクタからメソッドを呼び出す際に問題はありません。特にオブジェクトのメモリはすでに割り当てられています。

2

寿命がまだ始まっていないという主な理由は、コンストラクタが例外をスローするとデストラクタが実行されないことです。

2

注:私たちは

生涯の考慮事項は、実際にはかなり複雑で、いくつかのコンテキストを持つことができるように、それは、正確な記事を簡単にされていると思います。オブジェクトのコンストラクタを考慮

は、ビューの二つの異なる点があります

  • 外部:オブジェクト
  • 内部のユーザー、すなわち:つまり、あなたのコンストラクタとデストラクタを書く(特に)
  • ビューの外部の点から

、オブジェクトの寿命:

  • コンストラクタが正常に完了したら
  • はデストラクタが

を実行し始めたとき、それはあなたがオブジェクト半ばに建設または半ば破壊にアクセスしようとする悪いことは(TM)が起こることを意味終了始まります。これは主にマルチスレッドプログラムに関係しますが、オブジェクトへのポインタを基底クラスに渡すと起こります...

...内部の視点。それはもっと複雑です。あなたが確信していることは、必要なメモリが割り当てられていることですが、オブジェクトの一部はまだ完全には初期化されていない可能性があります。

  • コンストラクタの本体で、クラスの属性と基底を使用できます(初期化されています)。通常は関数を呼び出します(仮想呼び出しは避ける必要があります)。
  • それは、派生オブジェクトがまだ初期化されていない基底クラス(仮想呼び出しのため制限)
関連する問題