2017年12月21日
《その191》 仮想関数,仮想デストラクタ,多相的クラス
virtual無し と virtual有りの 短いプログラムを比較して、仮想関数,仮想デストラクタ,多相的クラス の再確認をしてみたいと思います。
◆ virtual無し
// ------------------------------------
#include <iostream>
using namespace std;
class Aaa {
public:
Aaa() { cout << "constructor Aaa\n"; }
~Aaa() { cout << "destructor Aaa\n"; }
void f() const { cout << "Aaa\n"; }
};
class Bbb : public Aaa{
public:
int b = 20;
Bbb() { cout << "constructor Bbb\n"; }
~Bbb() { cout << "destructor Bbb\n"; }
void f() const { cout << "Bbb\n"; }
};
void func(Aaa& x) {
x.f();
}
int main() {
cout << "(1)\n";
Aaa* ptr = new Bbb;
cout << "------\n";
cout << "(2)\n";
delete ptr;
cout << "------\n";
cout << "(3)\n";
Bbb b;
cout << "------\n";
cout << "(4)\n";
func(b);
cout << "------\n";
cout << "(5)\n";
}
// ------------------------------------
(1)
動的に領域を確保して、Bbb型オブジェクトを作成するので、
基底クラスのコンストラクタ Aaa が呼び出され、
→ "constructor Aaa"を表示
次いで、派生クラスのコンストラクタ Bbb が呼び出されます。
→ "constructor Bbb"を表示
(2)
Aaa, Bbb は多相的クラスではないのでポインタ ptr は静的な型 Aaa*。よって、デストラクタ ~Aaa が呼ばれます。
→ "destructor Aaa"を表示
(3)
Bbb型オブジェクトを作成するので、
基底クラスのコンストラクタ Aaa が呼び出され、
→ "constructor Aaa"を表示
次いで、派生クラスのコンストラクタ Bbb が呼び出されます。
→ "constructor Bbb"を表示
(4)
関数 func の仮引数は Aaa&型。f() は仮想関数ではないので、Aaa::f() が呼び出されます。
→ "Aaa"を表示
(5)
プログラムの終了時に オブジェクト b を破棄するので、
デストラクタ ~Bbb が呼び出され、
→ "destructor ~Bbb"を表示
次いで、デストラクタ ~Aaa が呼び出されます。
→ "destructor ~Aaa"を表示
◆ virtual有り
// ------------------------------------
#include <iostream>
using namespace std;
class Aaa {
public:
Aaa() { cout << "constructor Aaa\n"; }
virtual ~Aaa() { cout << "destructor Aaa\n"; }
virtual void f() const { cout << "Aaa\n"; }
};
class Bbb : public Aaa{
public:
int b = 20;
Bbb() { cout << "constructor Bbb\n"; }
~Bbb() { cout << "destructor Bbb\n"; }
void f() const { cout << "Bbb\n"; }
};
void func(Aaa& x) {
x.f();
}
int main() {
cout << "(1)\n";
Aaa* ptr = new Bbb;
cout << "------\n";
cout << "(2)\n";
delete ptr;
cout << "------\n";
cout << "(3)\n";
Bbb b;
cout << "------\n";
cout << "(4)\n";
func(b);
cout << "------\n";
cout << "(5)\n";
}
// ------------------------------------
(1)
動的に領域を確保して、Bbb型オブジェクトを作成するので、
基底クラスのコンストラクタ Aaa が呼び出され、
→ "constructor Aaa"を表示
次いで、派生クラスのコンストラクタ Bbb が呼び出されます。
→ "constructor Bbb"を表示
(2)
Aaa, Bbb は多相的クラスであるからポインタ ptr は動的な型 Bbb*。よって、
デストラクタ ~Bbb が呼ばれ、
→ "destructor ~Bbb"を表示
次いで、デストラクタ ~Aaa が呼ばれます。
→ "destructor ~Aaa"を表示
(3)
Bbb型オブジェクトを作成するので、
基底クラスのコンストラクタ Aaa が呼び出され、
→ "constructor Aaa"を表示
次いで、派生クラスのコンストラクタ Bbb が呼び出されます。
→ "constructor Bbb"を表示
(4)
関数 func の仮引数は Aaa&型ですが、f() が仮想関数なので、Bbb::f() が呼び出されます。
→ "Bbb"を表示
(5)
プログラムの終了時に オブジェクト b を破棄するので、
デストラクタ ~Bbb が呼び出され、
→ "destructor ~Bbb"を表示
次いで、デストラクタ ~Aaa が呼び出されます。
→ "destructor ~Aaa"を表示
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7112204
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック