class B : public A { };
A* p1 = new B; // B may be larger than A :OK [Line 1]
B* p2 = new A; // B may be larger than A :Not OK [Line 2]
私は著者の1行目と2行目
にコメントで何を意味するのか理解していないのはなぜ私たちがすることはできません2行目?それが含まれているメンバ変数の観点から - -
class B
はこれ、class A
に由来し、それはAが持っているすべてのもの、それは自分自身を追加することを選択したものを有することを意味します。あなたの単純なコードでは、Bは何も追加していませんが、追加のデータメンバーを持っていれば、格納するのに必要なメモリは明らかにA
よりも簡単です。 Aがない仮想メンバ関数を追加すると、コンパイラは、Bの中に、virtual
メンバ関数のアドレスをリストした仮想ディスパッチテーブルのアドレスを記録するポインタを追加することが期待できます。コンパイラは、それが気に入ったら埋め込みを自由に追加することもできます。
したがって、一般的なケースでは、派生クラスのサイズは、その基本クラスのサイズである>=
です。ここで
A* p1 = new B; // B may be larger than A :OK [Line 1]
、しかし多くのスペースB
が実際に必要とヒープ/フリーストアから割り当てられ、そのメモリのアドレスはp1
に格納されています。 B
がA
より大きい場合、それは違いはありません - とにかくそれはどこかにあります - 重要なことはB*
がA*
に格納できることが保証されていることです。ここで
B* p2 = new A; // B may be larger than A :Not OK [Line 2]
、新しいA
はヒープ上に作成されているが、プログラマはそのアドレスのB
があることをコンパイラに指示しようとしています。コンパイラは(強制されない限り)それを信じません - あなたは単にコンパイラの時間エラーを取得します。あなたが(例えば、P2 =(Bの*)コンパイラを強制(新しいA)) to treat the memory address in
P2 as if it were an
B , then it may later try to access additional data it expects to be part of any
B which simply doesn't exist in any
A`行う場合:追加のデータメンバー、仮想ディスパッチポインタなどを...ここ
実際、基本クラスの空の空きがあり、奇妙なABIレイアウトが原因で、 'A'が' B'よりも大きくなる可能性があります。 –