9

次のコードは、「C++オブジェクトモデルの内部」という本からのものです。

#include <iostream>  
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
     cout<<sizeof(X)<<" "<<sizeof(Y)<<" "<<sizeof(Z)<<" "<<sizeof(A)<<endl;
     return 0;
}

私のコンピューター(Windows、VS2010)では、出力は次のとおりです。

1 4 4 8

これが私の質問です

1、sizeof(X)= 1

この本は、Xタイプが2つのインスタンス、たとえばxaとxbを生成する場合を示しています。コンパイルは、xaとxbが異なるアドレスを持つことができるようにAにバイトを挿入します。理由がよくわかりません。

2、sizeof(Y)= 4

仮想継承を使用することで、追加の仮想ポインターができますか?これは、ポリモーフィズムの仮想ポインターとは異なる可能性があると思います。Yのメモリレイアウトを教えてもらえますか?

ありがとうございました!

4

4 に答える 4

6
  1. クラスが空の場合、コンパイラは新しい1文字であるため、別のオブジェクトを生成できます
  2. sizeof(Y)=4 これは仮想継承であるため、コンストラクトは 32 ビット システムで 4 バイトの vptr テーブルを生成します
  3. Visual Studio を使用している場合は、プロパティで /d1reportAllClassLayout を使用します->C/C++/Command でオブジェクト レイアウト クラスを生成します Y オブジェクト レイアウトは Visual Studio になります。
  4. Stanley B. Lippman 著の「Inside C++ object model」という本は、これを非常によく説明しています。

 
        class Y size(4):
            +---
            0     | {vbptr}
            +---
            +--- (virtual base X)
            +---
Y::$vbtable@: 0 | 0 1 | 4 (Yd(Y+0)X)

vbi: class offset o.vbptr o.vbte fVtorDisp X 4 0 4 0
于 2012-10-31T11:50:48.103 に答える
1

Aオブジェクトには、Yオブジェクト、Zオブジェクト(この順序で)、および1つのXオブジェクト(YとZのポインターによって参照される)のみが含まれます。これは、YとZの両方が実質的にXから継承するためです。つまり、多重継承が発生すると、 1つのXオブジェクトのみを再生すると、子クラス内でインスタンス化されます。Aにはまだ2つのオブジェクト(1つはY、1つはZ)があり、したがってsizeof = 8です(両方ともsizeof = 4であるため)。ただし、XオブジェクトへのYとZの両方のポインターは、同じアドレスを指します。

継承ツリーは次のようになります。

  X
 / \
 Y Z
 \ /
  A
于 2012-10-31T11:52:21.593 に答える
1

空のクラスの sizeof は常に 1 を返します。これは、空のクラスの 1 つのダミー バイトです。

A は仮想テーブルに 2 つのエントリを保持します。1 つは Y 用、もう 1 つは Z 用です。

したがって、2 つのポインターのサイズ、つまり 8 です。

Y と Z は両方とも仮想テーブルに X のエントリを 1 つ持つため、サイズは 4 です。

于 2012-10-31T11:41:32.260 に答える
0

クラスが少なくとも 1 バイトである必要がある理由は、X の配列があるからです。それらが 0 バイトの場合、&array[1] は &array[3] と同じアドレスになり、誰も予期せず、コードが壊れます。それをチェックするためにコードを書かなければならず、通常は意味がありません。

Yは単に

static void* virtual_ptr1 //note this is in virtual table and cannot be edited  

vtables (クラスおよび仮想関数への仮想ポインター) は、手動/コードで編集できない (または少なくともすべきではない) 静的変数と考えることができます。コンパイラが予約した静的変数と考えてください

于 2012-10-31T12:32:28.110 に答える