以下のプログラムがあるとしましょう:
class A
{ public:
virtual fun(){};
};
class B:public A
{ public:
virtual fun(){};
};
int main()
{
A a1;
B b1;
}
私の質問は、このプログラムを実行するvtables
と、いくつ作成されるのでしょうか?vptrs
実装に大きく依存しますが、通常、仮想関数を持つクラスごとに1つのvtableオブジェクト(仮想関数を持たないクラスまたは仮想関数を必要としないクラス)と、vtableを持つクラスのオブジェクトごとに1つのvptr(を指す)を取得します。クラスのvtable)。
複数の継承と仮想基本クラスがある場合、状況はさらに複雑になります。これは、さまざまな方法で実装できます。一部の実装では、追加の基本クラスごとに追加のvtableを使用します(したがって、クラスごとの基本クラスごとにvtableを使用することになります)が、他の実装では、追加情報を含む単一のvtableを使用します。これにより、オブジェクトごとに複数のvptrが必要になる場合があります。
Bのvirtual
キーワードは関係ありません。関数が基本クラスで仮想である場合、派生クラスで仮想になります。
このプログラムは、次のように最適化できます。
int main(){}
したがって、「なし」が可能です。
基本的に、2。1つは、、 class A
1つはclass B
(vftables)、2つはvfptrs、1a1
つはb1
。
ただし、これは標準で義務付けられているものではないため、何も義務付けられていない可能性があります。(通常、実装はvftablesを使用しますが、必須ではありません。
@Rに注意してください。最適化をオンにしたMartinhoFernandesでは、オブジェクトは作成されないため、vfptrs
。
これは厳密に実装に依存することに注意してください。C ++標準では、またはについては説明されて
いません。仮想メカニズムは、コンパイラの実装の詳細として省略されています。したがって、実際には、コンパイラはまたはを使用せずに実装できます。ただし、ほとんどすべての既知のコンパイラは、およびを使用して実装します。vptr
vtable
vptr
vtable
vptr
vtable
上記を前提として、あなたの質問に答えるには:
各クラスには独自の仮想テーブルがあります。
各オブジェクトには独自の仮想ポインタがあります。
仮想テーブルは、基本クラスに少なくとも 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() に他なりません。これで疑いが晴れることを願っています。