継承と初期化
継承時のコンストラクタ
派生クラスのオブジェクトのコンストラクタやデストラクタはどのようになるのでしょう
コンストラクタやデストラクタは、普通の方法で定義することができます
しかし、派生クラスには基本クラスのコンストラクタがあるはずです
正確に初期化するためには、基本クラスのコンストラクタも実行させなければいけません
実は、コンストラクタは基本クラスから派生クラスの順番で実行されます
まず、基本クラスのコンストラクタが呼び出され、次に派生クラスのコンストラクタが実行されます
この順番は基本クラスが、派生クラスの情報がないという理由からです
#include<iostream>
using namespace std;
class Kitty {
public:
Kitty() { cout << "Kitty on your lap\n"; }
};
class LOVE_HINA : public Kitty {
public:
LOVE_HINA() { cout << "LOVE HINA\n"; }
} obj ;
int main() {
return 0;
}
このプログラムを実行すると
Kitty on your lap
LOVE HINA
という文字列がコンソールに出力されます
これを見れば、基本クラスのコンストラクタが先に実行されているのが確認できますね
しかし、このままでは基本クラスのコンストラクタに引数を渡せません
あくまでオブジェクトの初期化時に指定するのは派生クラスのコンストラクタです
そこで、基本クラスのコンストラクタに引数を渡す場合
派生クラスのコンストラクタから明示的に基本クラスのコンストラクタに引数を渡します
派生クラスのコンストラクタから、基本クラスのコンストラクタに引数を渡す場合
派生クラスのコンストラクタの定義で、次のような構文を記述します
derived(arg-list) : base(arg-list) {
statements...
}
derived()は派生クラスのコンストラクタ、base()は基本クラスのコンストラクタです
派生クラス、基本クラスともに引数を指定し、その引数が同じものでもかまいません
#include<iostream>
using namespace std;
class Kitty {
public:
Kitty(char *str) { cout << str; }
};
class Nekoneko_Zoo : public Kitty {
public:
Nekoneko_Zoo() : Kitty("Kitty on your lap\n") {
cout << "Nekoneko_Zoo\n";
}
} obj ;
int main() {
return 0;
}
派生クラスのコンストラクタ Nekoneko_Zoo() から
基本クラスへ引数 "Kitty on your lap" を渡してきます
デストラクタ
継承におけるデストラクタの場合、派生クラスのオブジェクトが破棄されると
デストラクタの発生順序は、コンストラクタのそれとは逆をたどります
これは、基本クラスのデータを先に破壊してしまうと
派生クラスのデストラクタが発生した時にデータが壊れている可能性があるからためです
積み重ねっている頂点からデータを崩していく感じです
#include<iostream>
using namespace std;
class Kitty {
public:
~Kitty() { cout << "Kitty on your lap\n"; }
};
class Nekoneko_Zoo : public Kitty {
public:
~Nekoneko_Zoo() { cout << "Nekoneko_Zoo\n"; }
} obj ;
int main() {
return 0;
}
この場合、派生クラス Nekoneko_Zoo のデストラクタから実行されます