C++虚関数継承と虚継承

3064 ワード

虚関数継承と虚継承はまったく異なる2つの概念である.
虚関数継承は多態性を解決し、ベースクラスポインタで派生クラスオブジェクトを指すと、ベースクラスポインタが虚関数を呼び出すと、派生クラスの虚関数が自動的に呼び出されます.これが多態性、すなわち動的アセンブリです.
虚継承はメモリを節約するためであり,多重継承に特有の概念である.菱形継承形式に適用されます.
例えば、BはA、CはA、DはB、Cに継承され、Dは明らかに2回Aを継承する(図1).したがって、スペースを節約するために、B、C対Aの継承を仮想継承と定義することができ、Aは仮想ベースクラスとなる(図2).コードは次のとおりです.
A A///\B C//\/D(図1)(図2)
class A; 
class B:vitual public A; 
class C:vitual public A; 
class D:public B,public C; 

虚が継承されると、サブクラスには自分の虚関数テーブルを指すポインタがあり、親を指す虚クラスポインタも追加され、親のすべての内容も含まれます.
虚継承時に子クラスの親に虚関数がある場合、親クラスの虚テーブルの内容を含まない虚テーブルが再構築されます.通常の継承では、親の虚表に基づいて虚表を作成します.これは、虚継承中性子クラスの親にそれぞれの虚関数がある場合、子クラスには2つの虚関数テーブルポインタがあり、1つは親クラスを指す虚テーブル、1つは子クラスを指す虚テーブルであり、通常の継承には1つの子クラスを指す虚テーブルのポインタしかないことを意味します.コードの説明:
class A
{
    int k;
public:
    virtual void aa(){};
};

class B:public virtual A
{
    int j;
public:
    virtual void bb(){};
};

class C:public virtual B
{
    int i;
public:
    virtual void cc(){};
};

int main()
{
    cout << sizeof(A) << endl;
    cout << sizeof(B) << endl;
    cout << sizeof(C) << endl;
    system("pause");
    return 0;
}

出力結果は、8、20、32です.
どうやって来ましたか.クラスAには整数変数k(4バイト)、ダミーテーブルポインタ(4バイト)が含まれているので、合計8バイトです.クラスBでは、1つの整数変数j(4バイト)、1つの虚表ポインタ(4バイト)があり、B虚はAに継承されるため、クラスAを指すすべての虚類ポインタ(4バイト)があり、同時にクラスAの整数変数k(4バイト)とクラスAの虚表ポインタ(4バイト)も含まれるため、合計20バイトである.類C同理.
上記のコードを通常継承に変更すると、出力結果は8、12、16となります.ダミークラスポインタがなくても、複数のダミーテーブルポインタはありません.