3

C++ 仕様では、非仮想クラスのインスタンスに vtable ポインター用のメモリを含めることが許可されていますか? 私がこれを尋ねているのは、同僚が以前 C++ コンパイラを使用した際に次のことが起こったと言ったからです。

  class MyClass
  {

     public:

     HeaderStruct header; //This had extra words
     BodyStruct     message_body;
  };

次に、コードを次のように変更し、余分な単語を削除しました。

  struct MyClass
  {

     HeaderStruct header; //This did not have extra words
     BodyStruct     message_body;
  };

これらのタイプはどれも仮想ではなく、仮想のものから派生したものでもありません。したがって、おそらくこの特定のコンパイラは、構造体インスタンスではなく、クラス インスタンスの vptr にメモリを割り当てたという理論がありました。そのため、そのようなコンパイラの動作が仕様によって排除されているかどうかを判断しようとしています。

ありがとう!

ケン

4

4 に答える 4

3

クイック検索でオンライン リファレンスを見つけることはできませんが、コンパイラは任意のクラスのレイアウトで何でも実行できると確信しています。特に、仮想メソッドを持たないクラスでは、vftp を配置するかどうかは、その日の気分に応じて、classor struct(デフォルトのアクセス指定子を除いて C++ では同等です)として宣言されているかどうかに応じて許可されます。月、またはその他。私が知っている唯一の制限は、派生オブジェクトの上部が最初の (非仮想) 基本クラスのレイアウトと一致する必要があるということです。そして、それが最初のものである必要があるかどうかさえわかりません。

オブジェクトのレイアウトに関する特定のコンパイラの決定に依存するべきではありません。多くのコンパイラは、例外なくすべてのオブジェクトに vftp を配置します。これは、実行時の型情報をデバッガに提供するため、または単に作業を楽にするためです。そうでない人もいます。sizeofオペレーターを介さない限り、合理的な方法で知ることはできません。

于 2011-04-27T02:30:07.707 に答える
2

「仮想クラス」などというものはありません。クラス名の前にキーワードを使用する仮想継承を意味するかもしれませんvirtualが、仮想性はクラス自体ではなく、継承関係に適用されます。または、単に仮想関数を含むクラスを意味しているのかもしれません。

いずれにせよ、C++ 仕様は仮想テーブルについて何も述べていません。それらは実装に固有のものです。通常、仮想テーブルが追加されるのは、クラスに仮想関数が含まれているか、仮想ベースがあるか、仮想ベースを持つ他のクラスから継承されている場合のみです。しかし、実装がすべてのクラスのすべてのインスタンスに仮想テーブルを配置することは完全に有効です。

于 2011-04-27T02:29:25.407 に答える
-1

クラスの仮想修飾子は、クラスから複数回継承する可能性がある場合にのみ使用されます。I / Oストリームライブラリでは、istreamとostreamの両方がios_baseから継承され、iostreamはistreamとostreamの両方を継承します。仮想モディファイアを使用すると、基本クラスのメンバーのコピーを2つ取得せずに、2回継承できます。

ただし、非仮想クラスであっても、どのメソッドも仮想にすることができます。したがって、どのクラスもvtableを持つことができます。

しかし、あなたの質問に対する本当の答えは:)クラスと構造体はほとんど同じですが、クラスではメンバーはデフォルトでプライベートですが、構造体ではデフォルトでパブリックです。

于 2011-04-27T02:19:11.167 に答える