13

以下のプログラムがあるとしましょう:

class A
{     public:
      virtual fun(){};
};
class B:public A
{     public:
     virtual fun(){};
};
int main()
{
     A a1;
     B b1;
 }

私の質問は、このプログラムを実行するvtablesと、いくつ作成されるのでしょうか?vptrs

4

6 に答える 6

15

実装に大きく依存しますが、通常、仮想関数を持つクラスごとに1つのvtableオブジェクト(仮想関数を持たないクラスまたは仮想関数を必要としないクラス)と、vtableを持つクラスのオブジェクトごとに1つのvptr(を指す)を取得します。クラスのvtable)。

複数の継承と仮想基本クラスがある場合、状況はさらに複雑になります。これは、さまざまな方法で実装できます。一部の実装では、追加の基本クラスごとに追加のvtableを使用します(したがって、クラスごとの基本クラスごとにvtableを使用することになります)が、他の実装では、追加情報を含む単一のvtableを使用します。これにより、オブジェクトごとに複数のvptrが必要になる場合があります。

Bのvirtualキーワードは関係ありません。関数が基本クラスで仮想である場合、派生クラスで仮想になります。

于 2012-01-19T19:31:22.560 に答える
14

このプログラムは、次のように最適化できます。

int main(){}

したがって、「なし」が可能です。

于 2012-01-19T19:32:04.433 に答える
9

基本的に、2。1つは、、 class A1つはclass B(vftables)、2つはvfptrs、1a1つはb1

ただし、これは標準で義務付けられているものではないため、何も義務付けられていない可能性があります。(通常、実装はvftablesを使用しますが、必須ではありません。

@Rに注意してください。最適化をオンにしたMartinhoFernandesでは、オブジェクトは作成されないため、vfptrs

于 2012-01-19T19:31:50.623 に答える
6

これは厳密に実装に依存することに注意してください。C ++標準では、またはについては説明されて
いません。仮想メカニズムは、コンパイラの実装の詳細として省略されています。したがって、実際には、コンパイラはまたはを使用せずに実装できます。ただし、ほとんどすべての既知のコンパイラは、およびを使用して実装します。vptrvtablevptrvtablevptrvtable

上記を前提として、あなたの質問に答えるには:

各クラスには独自の仮想テーブルがあります。
各オブジェクトには独自の仮想ポインタがあります。

于 2012-01-19T19:30:43.417 に答える
4

仮想テーブルは、基本クラスに少なくとも 1 つの仮想関数が存在する場合にのみ作成されます。これは、派生クラスに何らかの方法で継承されます。派生クラス B から virtual キーワードを削除しても問題はありません。すでに仮想的な楽しみを持っているからです。 () の A. したがって、仮想テーブルの数は (クラスごとに) 2 になり、仮想ポイントの数もオブジェクトごとに 2 になります。A の VTABLE---v_ptr* ,A::fun()

& VTABLE for B--- V_ptr*(A から継承されたもの),B::fun()/* B は A::fun と B の fun() の両方にアクセスできますが、A::fun() について述べたので仮想 B の仮想テーブルは関数の最も派生したバージョンである fun() で満たされているため、これは B::fun() に他なりません。これで疑いが晴れることを願っています。

于 2013-04-03T20:14:58.603 に答える