c++デフォルト構造関数の概要
2593 ワード
コンパイラがデフォルトのコンストラクタを合成するのはいつですか?
答え:コンパイラがそれを必要とするとき!(プログラムがデフォルトのコンストラクタを必要とする場合、それはプログラマの責任であり、プログラマが自分で定義すべきである)そして合成されたコンストラクタはコンパイラに必要な行動のみを実行する.
注意:1.コンストラクション関数を持たないすべてのクラスがコンパイル時にデフォルトのコンストラクション関数を生成するわけではありません(しかし、一部の大学の先生は授業の便宜上このように話しています).
2.コンパイラは、クラスに宣言されたコンストラクション関数が表示されない場合にのみ、クラスにデフォルトのコンストラクション関数を生成します.
例:
エラー:main関数でbarオブジェクトを定義すると、コンパイラはデフォルトのコンストラクション関数を生成してbarオブジェクトを初期化します.
正しい思考:コンパイラはデフォルトのコンストラクション関数を合成しません.コンパイラはコンストラクション関数を必要としないからです.クラスのデータメンバーの初期化は,プログラマのことであり,プログラマが自分で構造関数を定義して行うべきである.
コンパイラは、デフォルトのコンストラクタを合成する必要があると考えている4つの場合があります.
1.Default Constructor付きMember Class Object
ケース1:class Aにコンストラクション関数がなく、クラスのデータメンバーオブジェクトbが含まれており、bのクラスClass Bにデフォルトコンストラクション関数がある場合、コンパイラはクラスAのオブジェクトoba jectを定義するときにデフォルトコンストラクション関数を合成します.(オブジェクトaを構築する際にクラスBのデフォルトコンストラクタを呼び出してbを処理する必要があるため、aのデフォルトコンストラクタを合成する必要がある)
例:
上記のコードのクラスAは、aを構築する際に、コンパイラが生成するデフォルトのコンストラクタを生成し、合成されたコンストラクタに必要なコードを含み、class Bのデフォルトのコンストラクタを呼び出してクラスAのデータメンバーbを処理することができる.注意:合成されたコンストラクタは、プログラムのニーズではなく、コンパイラのニーズを満たすだけで、彼はメンバーstrを初期化しません
合成されたコンストラクション関数の擬似コードは次のとおりです.
ケース2:上記の例では、クラスAにデフォルトのコンストラクション関数が含まれている場合、クラスA関数は次のようになります.
この場合、クラスAはデフォルトのコンストラクタを定義していることを示すため、コンパイラはクラスAのデフォルトのコンストラクタを合成しませんが、コンパイラはクラスBのコンストラクタの開始位置(プログラマが書いたコードの前)にクラスBのコンストラクタを呼び出すためのコードをこっそり挿入します.この問題では、str=nullptrにコードが挿入されます.前
2.Default Constructor付きBase Class
コンストラクション関数のないクラスがデフォルトコンストラクション関数を持つベースクラスから派生した場合、この派生クラスは親クラスのデフォルトコンストラクション関数を呼び出すために合成されます.呼び出し順は宣言順
3.Virtual Function付きClass
classはvirtual functionを宣言または継承した
クラスには虚関数が存在するため、クラスには多態時に使用する虚関数テーブルが含まれます.したがって、クラスのオブジェクトを生成するときに、オブジェクトに虚関数テーブルを指す虚関数ポインタが必要です.クラスはデフォルトの構造関数を合成して虚関数ポインタを初期化する必要があります.
4.Virtual Base Classを持つClass
例えばレンガ型継承関係は,重複継承を解決するために虚継承を用いた.
クラスの継承には虚継承関係があるため、虚継承クラスは同じ虚継承親クラスのオブジェクトを共有します.この共有はポインタで行われます.このポインタを初期化するには、クラスもデフォルトの初期化関数を合成する必要があります.
以上の総括はもし间违いがあるならば指摘して下さい、みんなは共に进歩して、ありがとうございます
答え:コンパイラがそれを必要とするとき!(プログラムがデフォルトのコンストラクタを必要とする場合、それはプログラマの責任であり、プログラマが自分で定義すべきである)そして合成されたコンストラクタはコンパイラに必要な行動のみを実行する.
注意:1.コンストラクション関数を持たないすべてのクラスがコンパイル時にデフォルトのコンストラクション関数を生成するわけではありません(しかし、一部の大学の先生は授業の便宜上このように話しています).
2.コンパイラは、クラスに宣言されたコンストラクション関数が表示されない場合にのみ、クラスにデフォルトのコンストラクション関数を生成します.
例:
// Fool
class Foo{
public:
int val;
Foo *pnext;
}
int main(){
Foo bar;
cout<
エラー:main関数でbarオブジェクトを定義すると、コンパイラはデフォルトのコンストラクション関数を生成してbarオブジェクトを初期化します.
正しい思考:コンパイラはデフォルトのコンストラクション関数を合成しません.コンパイラはコンストラクション関数を必要としないからです.クラスのデータメンバーの初期化は,プログラマのことであり,プログラマが自分で構造関数を定義して行うべきである.
コンパイラは、デフォルトのコンストラクタを合成する必要があると考えている4つの場合があります.
1.Default Constructor付きMember Class Object
ケース1:class Aにコンストラクション関数がなく、クラスのデータメンバーオブジェクトbが含まれており、bのクラスClass Bにデフォルトコンストラクション関数がある場合、コンパイラはクラスAのオブジェクトoba jectを定義するときにデフォルトコンストラクション関数を合成します.(オブジェクトaを構築する際にクラスBのデフォルトコンストラクタを呼び出してbを処理する必要があるため、aのデフォルトコンストラクタを合成する必要がある)
例:
class B{
public:
B();//
B(int);//
//
..........
};
class A{
public:
B b;
char *str;
};
int main(){
A a;
if(a.str){
.....
}
return 0;
}
上記のコードのクラスAは、aを構築する際に、コンパイラが生成するデフォルトのコンストラクタを生成し、合成されたコンストラクタに必要なコードを含み、class Bのデフォルトのコンストラクタを呼び出してクラスAのデータメンバーbを処理することができる.注意:合成されたコンストラクタは、プログラムのニーズではなく、コンパイラのニーズを満たすだけで、彼はメンバーstrを初期化しません
合成されたコンストラクション関数の擬似コードは次のとおりです.
inline A::A(){
b.B::B()
}
ケース2:上記の例では、クラスAにデフォルトのコンストラクション関数が含まれている場合、クラスA関数は次のようになります.
class A{
public:
B b;
char *str;
B(){
str=nullptr;
}
};
この場合、クラスAはデフォルトのコンストラクタを定義していることを示すため、コンパイラはクラスAのデフォルトのコンストラクタを合成しませんが、コンパイラはクラスBのコンストラクタの開始位置(プログラマが書いたコードの前)にクラスBのコンストラクタを呼び出すためのコードをこっそり挿入します.この問題では、str=nullptrにコードが挿入されます.前
2.Default Constructor付きBase Class
コンストラクション関数のないクラスがデフォルトコンストラクション関数を持つベースクラスから派生した場合、この派生クラスは親クラスのデフォルトコンストラクション関数を呼び出すために合成されます.呼び出し順は宣言順
3.Virtual Function付きClass
classはvirtual functionを宣言または継承した
クラスには虚関数が存在するため、クラスには多態時に使用する虚関数テーブルが含まれます.したがって、クラスのオブジェクトを生成するときに、オブジェクトに虚関数テーブルを指す虚関数ポインタが必要です.クラスはデフォルトの構造関数を合成して虚関数ポインタを初期化する必要があります.
4.Virtual Base Classを持つClass
例えばレンガ型継承関係は,重複継承を解決するために虚継承を用いた.
クラスの継承には虚継承関係があるため、虚継承クラスは同じ虚継承親クラスのオブジェクトを共有します.この共有はポインタで行われます.このポインタを初期化するには、クラスもデフォルトの初期化関数を合成する必要があります.
以上の総括はもし间违いがあるならば指摘して下さい、みんなは共に进歩して、ありがとうございます