デフォルトコンストラクタの作成

9758 ワード

文章が始まる前に、まずc++初心者に対する2つのよくある誤解を指摘します.
一、任意のclassはdefault constructorを定義していない場合、1つに合成されます.
二、コンパイラが合成したdefault constructorは「class内の各data memberのデフォルト値」を明確に設定する
 
まず最初の誤解について議論しましょう.コンパイラはuser-declared constructorのないclassにdefault constructorを合成するのではなく、必要に応じてuser-declared constructorのないclassにdefault constructorを合成するだけです.それはいったいいつ必要なのでしょうか.まず、C++standardの一言を見てみましょう.「class Xについて、user-declared constructorがなければ、default constructorが暗黙(implicitly)に宣言されます......暗黙的に宣言されたdefault constructorはtrivial(無能な)constructorになります」.この言葉について、まず説明します.原話の暗黙の声明はコンパイラが彼に合成することを意味しません.trivial constructorについては、コンパイラは彼らに合成しません.コンパイラが合成するのはnontrivial default construtorだけで、いったいどれがnontrivial default constructorなのでしょうか.『Insider C++』では4つのケースが示されています.
1、1つのclassのメンバーにdefault constructor付きmember class objectを含む
1つのclassにメンバーオブジェクトが含まれており、このオブジェクトにdefault constructorがある場合、コンパイラはこのclassにdefault constructorを合成しますが、この合成動作は呼び出しの必要に応じてのみ生成されます.つまり、必要に応じて合成されます.
例:
    

  
  
  
  
  1. class Foo{  
  2.     public Foo();  
  3.     ......  
  4. }  
  5.  
  6. class Bar{  
  7.     Foo foo;  
  8.     char *str  
  9. }  
  10.  
  11. void foo_bar(){  
  12.    Bar bar;   //bar
  13.    if(str){}.....  

上記のコードでは、line 12、barはここで初期化しなければならない.この場合、コンパイラはBarにdefault constructorを合成し、default constructorにFooを呼び出すdefault constructorをコードで挿入するが、コンパイラがBarで合成したdefault constructorはstrを初期化せず、strを初期化する点がある.それはプログラマーがしなければならないことですが、合成されたdefault constructorは、コンパイラのニーズだけを満たし、プログラムのニーズを満たすことはありません.
classにdefault constructorを含むobjectが1つ以上含まれている場合、classに合成されたdefault constructorでは、objectの宣言順にobjectのdefault constructorが呼び出されます.
2、classはdefault constructor付きbase classに継承する
constructorのない派生クラスがdefault constructor付きbase classから継承されている場合、この派生クラスのdefault constructorはnontrivialとみなされ、nontrivialのdefault constructorではコンパイラが合成されます.合成したdefault constructorでbase classのdefault constuctorを呼び出す.
設計者が複数のconstructorを提供しているがdefault constuctorを提供する場合、コンパイラは新しいdefault constructorを合成するのではなく、既存のすべてのconstructorを拡張し、default constructorに必要なコードを挿入します.このような第1のケース、すなわちmenber objectが存在し、objectにdefault constructorが含まれている場合、これらのdefault constructorも呼び出され、base classのdefault constructorが呼び出された後に呼び出されます.
3、このclassにはvirtual functionがついています
1つのclassが1つのvirtual functionを宣言(または継承)したか、または1つの継承直列から派生したかにかかわらず、1つ以上のvirtual base classがある.いずれの場合も、userによって宣言されたconstructorが不足しているため、コンパイラはdefault constructorを合成する詳細を詳細に記録する.
コンパイル中は、次の拡張作業を行います.
(1)virtual function tableはコンパイラによって生成され、virtual functionsのアドレスが含まれている.
(2)コンパイラはvptrを合成し,各objectに挿入する.
合成したdefault constructorは、もちろんobjectごとにvptrの初期値を設定します.
 
4、virtual base class付きclass
このような状況については、私はまだ徹底的に研究していません.徹底的に研究した後、私はまたみんなに貼り付けます.
以上、最初の誤解についての議論ですが、2番目の誤解については、合成されたdefault constructorについては、base class subobjectやmember class objectを初期化するなど、必要なことしかできませんが、他のnonstatic data memberについては整数、ポインタ、配列などは初期化されません.それらはコンパイラにとって必要ではないからです.
まとめ:
以上、その2つの誤解についてお話ししました.皆さんに役に立つことを願っています.コンパイラはconstructorを宣言していないclassのためにdefault constructorを合成し、合成されたconstructorはコンパイラのニーズを満たすだけで、プログラムのニーズを満たすことはできません.彼らがタスク(コンパイラのニーズを満たす)を完了できるのは、「member objectまたはbase classのdefault constructor」または「vtblの作成とvptrの正確な初期化を含むvirtual functionメカニズムをobjectごとに初期化する」またはvirtual base classメカニズムを呼び出すことです..その4つの状況が存在せず、user-decleared constructorもないclassについては、implict trivial default constructorを持っていると言っていますが、実際には合成されていません.
 
だから、以上の2つの誤解は、すべて間違っていることがわかります.