C++講座6回です 今回はコンストラクタ・コピーコンストラクタ・デストラクタについてです 今回のサンプル &ref(constructer.zip); &ref(copyconstructer.zip); &ref(destructer.zip); クラスに自分が定義しなくてもデフォルトで定義されていて それぞれ、特定のタイミングで呼び出される特殊なメンバ関数があります ○コンストラクタ インスタンスが生成されたとき呼ばれる ○コピーコンストラクタ インスタンスの初期化時に呼ばれる ○デストラクタ インスタンスが破棄されたとき呼ばれる コンストラクタ・コピーコンストラクタ・デストラクタ を自分で定義すれば 定義した方の関数が呼ばれ 特定のタイミングで色々処理させることができます --------------- コンストラクタ名はクラス名と同じにする必要があります。 戻り値はありません。 コンストラクタは主にクラス内変数の初期化に使われます。 class Test{ public: // コンストラクタ(戻り値無し) Test(); }; // コンストラクタ実装 Test::Test(){ printf("コンストラクタが呼ばれました\n"); } コンストラクタには初期化子があります コンストラクタが呼ばれたときクラスのメンバ変数を初期化するのに使います コンストラクタ内でメンバ変数を代入演算しても良いのですが C++では初期化子を使うほうが一般的です(代入演算より若干早い) 以下コンストラクタの初期化子を使う例を挙げます 「:」 以下にメンバ変数と初期化する値を入れる連続で初期化する場合は「,」で区切ります class Test{ public: int HP; int MP; // コンストラクタ Test(); }; // コンストラクタ実装 Test::Test():HP(100),MP(10) {} また、コンストラクタはオーバロードすることができ、 その場合はインスタンス化するときの引数でコンストラクタの呼び出しも切り替わります class Test{ public: // コンストラクタのオーバーロード Test(int hp,int mp); }; // コンストラクタ実装 Test::Test(int hp,int mp):HP(hp),MP(mp) { printf("コンストラクタ(引数付き)が呼ばれました\n"); } int main(){ Test test(200,30); //生成 Test* ptest = new Test(300,20); // 動的生成 delete ptest; return 0; } 次にコンストラクタの全ソースを示しておきます どのようにインスタンス生成した場合でもコンストラクタは必ず呼ばれることを確認してみてください //main.cpp #include <iostream> class Test{ public: int HP; int MP; // コンストラクタ(戻り値無し) Test(); // コンストラクタのオーバーロード Test(int hp,int mp); }; // コンストラクタ実装 Test::Test():HP(100),MP(10) { printf("コンストラクタが呼ばれました\n"); } // コンストラクタ実装 Test::Test(int hp,int mp):HP(hp),MP(mp) { printf("コンストラクタ(引数付き)が呼ばれました\n"); } int main(){ Test test1; // インスタンス化 printf("test1 HP = %d,MP = %d \n\n",test1.HP,test1.MP); Test test2(200,30); // 引数付きインスタンス化 printf("test2 HP = %d,MP = %d \n\n",test2.HP,test2.MP); printf("動的インスタンスの場合\n"); Test* ptest1 = new Test(); // 動的インスタンス化も呼ばれる delete ptest1; printf("動的インスタンス引数付きの場合\n"); Test* ptest2 = new Test(300,20); // 動的インスタンス化引数付き delete ptest2; printf("\n配列の場合\n"); Test test[5]; // 配列の場合でも個数分呼ばれる return 0; } ------ コピーコンストラクタはコンストラクターのオーバロードで引数は必ず(const クラス名&) とします コピーコンストラクタはインスタンス初期化時のデータのコピーに使われます class Test{ public: // コピーコンストラクタを定義するときはコンストラクタの定義も必要 Test(){} // コピーコンストラクタ(戻り値なし) Test(const Test& obj); }; // コピーコンストラクタ実装 Test::Test(const Test& obj){ printf("コピーコンストラクタが呼ばれました\n"); } 次にコピーコンストラクタの全ソースを示しておきます インスタンスの初期化時にコピーコンストラクタは必ず呼ばれることを確認してみてください // main.cpp #include <iostream> class Test{ public: // コピーコンストラクタを定義するときはコンストラクタの定義も必要 Test(){} // コピーコンストラクタ(戻り値なし) Test(const Test& obj); }; // コピーコンストラクタ実装 Test::Test(const Test& obj){ printf("コピーコンストラクタが呼ばれました\n"); } int main(){ Test test1; Test test2 = test1; // インスタンスの初期化時にコピーコンストラクタ Test test2 = test1; // インスタンスの初期化時にコピーコンストラクタが呼ばれる test2 = test1; // 代入は初期化じゃないのでコピーコンストラクタは呼ばれない return 0; } ------------ デストラクタ名はクラス名と同じにします 先頭に~をつけます 戻り値はありません デストラクタはメンバ変数の後処理に使われます class Test{ public: // デストラクタ(戻り値なし ~(チルダ)を先頭につける) ~Test(); }; // デストラクタ実装 Test::~Test() { printf("デストラクタが呼ばれました\n"); } 次にデストラクタの全ソースを示しておきます インスタンスの寿命が付きたときにデストラクタは必ず呼ばれることを確認してみてください // main.cpp #include <iostream> class Test{ public: // デストラクタ(戻り値なし ~(チルダ)を先頭につける) ~Test(); }; // デストラクタ実装 Test::~Test() { printf("デストラクタが呼ばれました\n"); } int main(){ { Test test; } // ブロックの外でtestの寿命が尽きる、このときデストラクタが呼ばれる Test* ptest = new Test(); delete ptest; // 動的インスタンスが破棄されてもデストラクタは呼ばれる return 0; } #vote(ok、次行こ、次[0],(;^ω^)?[0])