c++継承の虚ベースクラス


仮想ベースクラスの概念:
マルチ継承派生クラスで継承されたベースクラスにもう1つの共通ベースクラスがある場合、この共通ベースクラスはマルチ継承派生クラスのオブジェクトに複数の共通ベースクラスサブオブジェクトを生成します.この共通ベースクラスをマルチ継承派生クラスで1つのベースクラスサブオブジェクトのみを生成するには、このベースクラスを仮想ベースクラスとして設定し、虚ベースクラスと略称する必要があります.
仮想ベースクラスを導入する目的は,共通ベースクラスがその派生クラスオブジェクトの中で1つのベースクラスサブオブジェクトのみを生成するように,二義的な問題を解決することである.
ダミーベースクラスの説明形式は次のとおりです.
Virtual<継承方法><ベースクラス名>
virtualは虚ベースクラスを説明するキーワードであり、虚ベースクラス説明は派生クラスを定義する際に派生クラス名の後ろにアンインストールするために使用されます.
次のプログラムを分析します.
<span style="font-size:18px;">class A//      D     
{
public:
	void f();
private:
	int a;
};
class B:virtual class A
{
protected:
	int b;
};
class C:virtual class A
{
protected:
	int c;
};
class D:public class B,public class C//      D
{
public:
	int g();
private:
	int d;
};</span>

プログラム分析:
1、派生クラスDのオブジェクトdを定義すると、d.f();の形式は合法的です.
2,定義void D::g()
                      {    f();}も合法的です.
3,定義A*pd;   pd=&d;合法的です.
ダミーベースクラスを導入すると,派生クラスには1つのダミーベースクラスのサブオブジェクトしか存在しない.クラスにダミーベースクラスがある場合、コンパイルシステムは、クラスのオブジェクトにダミーベースクラスのサブオブジェクトを指すポインタを生成します.このポインタをダミーベースクラスポインタと呼びます.
虚ベースクラスおよび派生クラスの構造関数
C++言語では,ダミーベースクラスのサブオブジェクトは,最も遠い派生クラスのコンストラクタによってダミーベースクラスのコンストラクタを呼び出すことによって初期化されることが規定されている.最も遠い派生クラスとは、多層の継承構造でオブジェクトが指定したクラスを作成することです.派生クラスに直接または間接のダミーベースクラスがある場合、派生クラスのコンストラクション関数のメンバー初期化リストには、ダミーベースクラスコンストラクション関数の呼び出しが含まれている必要があります.リストされていない場合は、派生クラス派生クラスオブジェクトのダミーベースクラスサブオブジェクトを初期化するために、ダミーベースクラスを表すデフォルトのコンストラクタです.仮想ベースクラスのサブオブジェクトが一度だけ初期化されることを保証するために、オブジェクトを作成する最も遠い派生クラスのコンストラクション関数で仮想ベースクラスのコンストラクション関数を呼び出すことを規定し、この派生クラスのベースクラスコンストラクション関数では、仮想ベースクラスコンストラクション関数の呼び出しを無視する.
C++言語には,派生クラスコンストラクタのメンバ初期化リストにおいて,非ベースクラスコンストラクタよりも虚ベースクラスコンストラクタの呼び出しが現れることが規定されている.
<span style="font-size:18px;">#include <iostream>
using namespace std;
class A
{
public:
	A(const char *s)
	{ cout<<s<<endl; }
};
class B:virtual public A
{
public:
	B(const char *s1,const char *s2):A(s1)
	{
		cout<<s2<<endl;
	}
};
class C:virtual public A
{
public:
	C(const char *s1,const char *s2):A(s1)
	{
		cout<<s2<<endl;
	}
};
class D:public B,public C
{
public:
	D(const char *s1,const char *s2,const char *s3,
		const char *s4):B(s1,s2),C(s1,s3),A(s1)//      D     
	{ cout<<s4<<endl; }
};
int main()
{
	D *ptr=new D("class A","class B","class C","class D");//     D   
	delete ptr;
	return 0;
}</span>

プログラム解析:派生クラスBとCにはダミーベースクラスAが用いられ,派生クラスDのオブジェクトには1つのベースクラスAのサブオブジェクトしか存在しない.出力された結果は、classA class B class C class D