class Nanika
{
int datum;
public:
Nanika(int x) : datum(x){
cout << "Nanikaのインスタンス"
<< datum << "が生成されました。" << endl;
}
void func() const{
cout << "Nanikaのインスタンス"
<< datum << "のfuncが呼ばれました。" <<endl;
}
};
~Nanika(){.....}
という形の関数です。ここでクラス名Nanikaの前にはチルダ(にょろ、と呼ぶ人も多いですね)があります。デストラクタは、必ずこの形でないといけません。{.....}の中の点々のところには実際の処理を書きます。この「処理」とは、つまり「インスタンスの後始末」ということです。しかし、今のクラスでは特別な後始末が不要なので、わざわざデストラクタを書くことはありません。(まあ、今までの入門の例はみなそうですね。)後始末が必要になる例はまた後で、ということで、今日はとにかくデストラクタを書いて遊んでみましょう。今の例では、次のようにします。 ~Nanika(){
cout << "Nanikaのインスタンス"
<< datum << "が消滅しました。" << endl;
}
//dest_sample.cpp
#include <iostream>
using namespace std;
class Nanika
{
int datum;
public:
//コンストラクタ
Nanika(int x) : datum(x){
cout << "Nanikaのインスタンス"
<< datum << "が生成されました。" << endl;
}
void func() const{
cout << "Nanikaのインスタンス"
<< datum << "のfuncが呼ばれました。" <<endl;
}
//デストラクタ
~Nanika(){
cout << "Nanikaのインスタンス"
<< datum << "が消滅しました。" << endl;
}
};
int main()
{
//プログラマがはじめから数値1、2を与えてインスタンスOne、Twoをつくる
Nanika One(1), Two(2);
One.func();
Two.func();
}
ここで、ちょっと一言。私はいつも、コンストラクタの引数を説明するときに「ユーザまたはプログラマから値をもらって、」と書きながら、「私の例はいつもユーザからもらうものばかりだなぁ」と思っていました。ここでようやくプログラマがあらかじめ初期値を与える例を出すことができました。(ほっ。)こんな風にしてよいのです。(もう、わかっていましたよね?)余談ですが、Nekoの生成なら
Neko Dora("ボス");
//dest_sample2.cpp
#include <iostream>
using namespace std;
class Nanika
{
int datum;
public:
//コンストラクタ
Nanika(int x) : datum(x){
cout << "Nanikaのインスタンス"
<< datum << "が生成されました。" << endl;
}
void func() const{
cout << "Nanikaのインスタンス"
<< datum << "のfuncが呼ばれました。" <<endl;
}
//datumの値を戻す関数をつけておく
int get_datum() const { return datum; }
//デストラクタ
~Nanika(){
cout << "Nanikaのインスタンス"
<< datum << "が消滅しました。" << endl;
}
};
//Nanikaの派生クラス
class NanikaNoKo : public Nanika
{
public:
//コンストラクタ
NanikaNoKo(int x) : Nanika(x){
cout << "NanikaNoKoのインスタンス"
<< get_datum() << "が生成されました。" <<
endl;
}
//デストラクタ
~NanikaNoKo(){
cout << "NanikaNoKoのインスタンス"
<< get_datum() << "が消滅しました。" <<
endl;
}
void func() const{
cout << "NanikaNoKoのインスタンス"
<< get_datum() << "funcが呼ばれました。" <<
endl;
}
};
//NanikaNoKoの派生クラス
class NanikaNoMago : public NanikaNoKo
{
public:
//コンストラクタ
NanikaNoMago(int x):NanikaNoKo(x){
cout << "NanikaNoMagoのインスタンス"
<<get_datum() << "が生成されました。" <<
endl;
}
~NanikaNoMago(){
cout << "NanikaNoMagoのインスタンス"
<< get_datum() << "が消滅しました。" <<
endl;
}
void func() const{
cout << "NanikaNoMagoのインスタンス"
<< get_datum() << "funcが呼ばれました。" <<
endl;
}
};
int main()
{
Nanika One(1), Two(2);
NanikaNoKo Three(3);
NanikaNoMago Four(4);
One.func();
Two.func();
Three.func();
Four.func();
}
Nanikaのdatumを派生クラスでも使いたいので、Nanikaにはget_datumというdatumを戻す関数を付け加えました。このプログラムを実行すると次のようになります。
例えば、オブジェクトThreeの生成のときに、
Nanikaのインスタンス3が生成されました。
NanikaNoKoのインスタンス3が生成されました。
そのため、まず、基底クラスNanikaのコンストラクタが呼び出され、次に派生クラスNanikaNoKoのコンストラクタが呼び出されるのです。
デストラクタが呼び出される順番はその逆です。実行例を見ながら、少し考えてみてください。