c++ベースクラスでは、なぜ構造関数を虚関数として宣言するのか

1966 ワード

クラスでは、コンストラクション関数はオブジェクトの初期化および関連操作に使用され、コンストラクション関数は虚関数として宣言できません.コンストラクション関数を実行する前にオブジェクトが作成されていないため、虚関数テーブルは存在しません.この場合、虚関数テーブルをクエリーすることはできません.そのため、どのコンストラクション関数を呼び出すかはわかりません.
構造関数は、オブジェクトの破棄が完了したときに対応するリソース解放作業に使用され、構造関数を虚関数として宣言できます.次の例を用いて,ベースクラス構造関数が虚関数として宣言される必要性を理解することができる.
#include
using namespace std;
class base
{
public:
	base();
  ~base();
private:
	int *a;
};
class derived:public base
{
public:
	derived();
	~dericed();
private:
	int *p;
};
base ()
{
	cout<

実行結果
    base constructor!
    derived constructor!
    base destructor!

上のプログラムを分析することができます:この例の中で2つのクラスを定義して、1つのベースクラス、1つは派生クラスで、その中の派生クラスとベースクラスはすべてそれぞれ自分の構造関数と構造関数を定義して、ベースクラスと派生クラスの中でそれぞれ1つのint型のポインタのメンバーの変数があって、ベースクラスの構造関数の中で、ポインタの変数aに10のint型の空間を割り当てましたベースクラスの構造関数はaが指す空間を解放するために用いられ,派生クラスの構造関数ではポインタメンバー変数に1000個の整数空間が割り当てられ,派生クラスの構造関数ではbポインタが指す記憶空間を解放するためである.メイン関数では、派生クラスオブジェクトを指すベースクラスタイプのポインタを作成し、pポインタが指すオブジェクトの記憶領域を解放します.
プログラムの実行結果を見て、プログラムが「base constructor」という文字列を印刷すると、ベースクラスのコンストラクション関数が呼び出され、その後「derived constructor」という文字が印刷され、同じ派生クラスのコンストラクション関数も呼び出されます.newオペレータで派生クラスオブジェクトを作成すると、まずベースクラスコンストラクタが呼び出され、次に派生クラスコンストラクタが呼び出されて入力された結果は、ベースクラスのメンバー変数aがコンストラクタによって10個の整数記憶領域が割り当てられ、派生クラスのメンバーbがコンストラクタによって1000個の整数記憶領域が割り当てられます.その後、プログラムは「base destructor」文字列を印刷し、ベースクラスの構造関数が呼び出され、aポインタが指す10個の整数メモリ空間が解放されたことを示した.しかし、その後派生クラスの解析関数は呼び出されず、派生クラスの解析関数を呼び出さないとbポインタが指す1000型のストレージスペースが解放されないため、メモリ漏れが発生します.この問題を解決するために、ベースクラスの解析関数数を虚関数として宣言することができます.変更後、ベースクラスの定義は次のようになります.
class base
{
public:
	base();
	vortual ~base();
private:
	int *a;
};

変更後のプログラムの実行結果:
 base constructor!
  derived constructor!
  derived destructor!
  base destructor!

ベースクラスの解析関数を虚関数と宣言すると、派生クラスの解析関数も自動的に虚解析関数となり、主関数ではベースクラスポインタpが派生クラスオブジェクトを指し、deleteがpポインタが指す記憶空間を解放すると派生クラスの解析関数が実行され、派生クラスの解析関数が実行されるとベースクラスの解析関数が実行され、ベースクラスから継承されたメンバー変数で消費されるリソースを解放します.