3

以下のコード スニペットを検討してください。

class A
{
};

class B:public virtual A
{
};

class C:public virtual A
{
};

class D:public B,public C
{
};

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

私は次のように出力を得ています:

1 4 4 8

クラスBとのサイズはC、 の作成により 4 バイトですvptrvirtual tableがクラス用に作成されBているということCですか? どうAですか?

一般に、コンパイラvirtual tableがダイヤモンドの継承を正確に作成するのはどのクラスですか?
仮想テーブルを作成するための決定はコンパイラ固有ですか?

上記の例または他のより良い例の文脈で答えてください。

4

4 に答える 4

0

はい、仮想ベースを持つクラスには、何らかのタイプの vtable または同等のものが必要です。実行時に実際の基本サブオブジェクトを検索するメカニズムが必要です! (仮想ベース サブオブジェクトは、直接継承するオブジェクトではなく、最も派生したオブジェクトの責任であることに注意してください。)

于 2012-07-30T10:18:02.927 に答える
0

コンパイラが VTABLES を生成する場合、VTABLES を必要とするすべてのクラス (仮想関数を含むなど) に対して生成します。

Aは VTABLE を必要としません => サイズ == 1 [最小サイズ]

Bには 1 つ必要 => サイズ == 4 [32 ビットを使用しています...]

Cも 1 つ必要 => サイズ == 4

Dも 1 つ必要 => サイズ == 8 (2 つのエントリ、VTABLE D が参照する各エントリに 1 つ)

于 2012-07-30T10:20:09.250 に答える
0

B、C、D の仮想テーブルが作成されます。B と C にはそれぞれ 1 つの VPTR がありますが、D には 2 つの VPTR があります。1 つは VTable の B 部分を指し、もう 1 つは VTable の C 部分を指します。

注: VTable は必須ではなく、継承関係を適切にモデル化できる限り、コンパイラは独自の実装を提供できます。(ただし、ほとんどのコンパイラは VTable を実装しています)

于 2012-07-30T10:21:38.840 に答える
0

コンパイラがvptrfor any クラスを作成しなければならないということは何もありません。とはいえ、実際のコンパイラはvptrs を生成する理由は 2 つあります。

  1. 仮想ディスパッチ(明らか)
  2. RTTI、たとえば必要に応じてdynamic_cast(それほど明白ではありません)

通常、クラスのエントリは、vtableRTTI が機能するのに十分な情報を提供するある種の「型情報」構造を指します。

これと同じ情報により、コンパイラは、たとえば , , のいずれかを にキャストした場合に何をすべきかをB*判断C*できます。単純に両方を集約します。D*A*BCvptrD

于 2012-07-30T10:22:35.313 に答える