1コンストラクタを仮想関数にすることはできません。デストラクタを仮想関数にすることができます
コンストラクターを仮想関数にすることはできません
- コンストラクターの実行後、仮想関数テーブルポインターを適切に初期化できます
デストラクタは仮想関数になることができます
- クラスを設計するときは、デストラクターを仮想関数として宣言することをお勧めします
プログラミング実験:構築、解体、仮想関数
// 41-1.cpp
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base()" << endl;
}
virtual ~Base()
{
cout << "~Base()" << endl;
}
};
class Derived : public Base
{
public:
Derived()
{
cout << "Derived()" << endl;
}
virtual ~Derived()
{
cout << "~Derived()" << endl;
}
};
int main()
{
Base* p = new Derived();
delete p;
return 0;
}
親クラスのポインターがサブクラスのオブジェクトを指すnew Derived();サブクラスのオブジェクトを作成すると、親クラスのコンストラクターが呼び出され、サブクラスのコンストラクターが呼び出されます。デストラクタが仮想関数でない場合、pは親クラスのポインターです。親クラスのデストラクタを呼び出しますが、サブクラスのコンストラクタは呼び出しません。
デストラクタは仮想関数として定義されます。ポリモーフィック属性に従って、ポイントされたオブジェクトが破棄されます。サブクラスDerivedが破棄されると、サブクラスデストラクタが最初に呼び出され、次に親クラスデストラクタが呼び出されます。
コンパイルして実行:
$ g++ 41-1.cpp -o 41-1
$ ./41-1
Base()
Derived()
~Derived()
~Base()
2仮想関数を呼び出すデストラクタを作成しても、ポリモーフィズムは発生しません
コンストラクターにポリモーフィックな動作はありません
- コンストラクターを実行すると、仮想関数テーブルポインターが正しく初期化されません。
デストラクタにポリモーフィックな動作はありません
- デストラクタが実行されると、仮想関数テーブルポインタが破棄されました
したがって、コンストラクタとデストラクタでポリモーフィックな動作は発生せず、現在のクラスで定義されている関数バージョンのみが呼び出されます。!!
ウィル
// 41-2.cpp
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base()" << endl;
func(); // 调用虚函数
}
virtual void func() // 增加虚函数
{
cout << "Base::func()" << endl;
}
virtual ~Base()
{
func(); // 调用虚函数
cout << "~Base()" << endl;
}
};
class Derived : public Base
{
public:
Derived()
{
cout << "Derived()" << endl;
func(); // 调用虚函数
}
virtual void func() // 增加虚函数
{
cout << "Derived::func()" << endl;
}
virtual ~Derived()
{
func(); // 调用虚函数
cout << "~Derived()" << endl;
}
};
int main()
{
Base* p = new Derived();
delete p;
return 0;
}
コンパイルして実行します。コンストラクタとデストラクタでポリモーフィックな動作は発生せず、現在のクラスで定義されている関数バージョンのみを呼び出します
$ g++ 41-2.cpp -o 41-2
$ ./41-2
Base()
Base::func()
Derived()
Derived::func()
Derived::func()
~Derived()
Base::func()
~Base()
3まとめ
1.コンストラクターを仮想関数にすることはできず、デストラクターを仮想関数にすることもできます
2.コンストラクターとデストラクターの両方が多態性を生成することはできません。