かそうかんすう


1.虚関数はクラス内で宣言され、形式は以下の通りである.
virtual<戻りタイプ><関数名>(パラメータリスト)
虚関数の宣言は通常の関数よりもvirtualが1つ多く、公有派生クラスではvirtualキーワードを省略することができ、派生クラスでは虚関数を書き換えるには、戻り値タイプのパラメータリストが一致する必要があります.そうしないと、同名の上書きが発生します.派生クラスは、共通の継承方式でベースクラスを継承する場合にのみ、虚関数の正常な使用があります.虚関数の使用例:
# include <iostream>
using namespace std;
# include <stdlib.h>
typedef void (*ptr)();
class A
{
public:
	A(int a):x(a){}
	virtual void print();
	int *getx(){return &x;}
private:
	int x;
};
void A::print()
{
cout<<"A"<<" "<<x<<endl;
}
class B:public A
{
public:
	B(int a,int b):A(a),x(b){}
	void print();
	
private:
	int x;
};
void B::print()
{
	cout<<"B "<<x<<endl;
}
int main()
{   
	B b(2,3);
	A a(1);
	A *p=&a;
	p->print();   //       print()
	p=&b;
	p->print();   //        print()
	cout<<(int *)(&a)<<endl;    //       
	cout<<(int *)*((int *)(&a))<<endl;     //      
	cout<<a.getx()<<endl;       //  x   
system("pause");
return 0;
}

上のコードの末尾には、虚関数テーブルの位置、最初の虚関数のエントリアドレス、変数xのアドレスが印刷されます.
虚関数アドレスは虚関数テーブルに保存され、派生クラスが虚関数を書き換えると、派生クラスの関数バージョンが対応するアドレスを占めます.複数のベースクラスがある場合、各ベースクラスに虚関数テーブルが割り当てられ、虚関数宣言の順序で関数のエントリアドレスが格納されます.同様に、派生クラスが虚関数を書き換えると、派生クラスの関数バージョンが対応する位置を占めます.
2.虚関数の制限
(1)コンストラクション関数を虚関数として定義することはできません.コンストラクション関数はオブジェクトが完全に構築される前に実行されるべきです.このとき、コンストラクションのダイナミックタイプはまだ完全ではなく、マルチステート性は使用できません.
(2)基底クラスの構造関数はしばしば虚関数として定義される.ベースクラスの解析関数が虚関数として定義されていない場合、ベースクラスポインタは派生クラスオブジェクトを同時に指し、この派生クラスオブジェクトを解析する際に不完全な解析が発生するため、ベースクラスの解析関数は虚関数として宣言する必要がある.
(3)静的メンバー関数とインライン関数は虚関数として宣言できない.インライン関数と静的メンバー関数には、マルチステートの特性はありません.