仮想関数の単純な構造から複雑な構造まで、あらゆる種類のケースがあります。必要な追加メモリの数を決定する要因は何ですか? 例えば
class A {virtual void F() {} };
class B : public A {virtual void F() {} };
A と B は、仮想関数のないクラスと比較して、どれだけ多くのメモリを必要としますか? 2 つの仮想関数を使用した別の例
class A {virtual void F() {} virtual void G() {} };
class B : public A {virtual void F() {} virtual void G() {} };
そして例3
class A {virtual void F() {}; virtual void G() {} };
class B : public A {virtual void F() {} };
[--------------- 興味深い質問を追加 ------------------]
すべての仮想メソッドには仮想メソッド テーブルがありますか? もしそうなら、いくつかの仮想メソッドを持つクラス(オブジェクトではありませんよね?VPTRは静的だと思います。)には、仮想メソッドごとにいくつかのVPTRが必要だと思います。右?
すべての仮想メソッドに対して 1 つのテーブルだけを作成し、1 つのクラスに VPTR を 1 つだけ配置することは可能ですか?
また、直接 VPTR を使用しているため、仮想関数の呼び出し速度は手動 ifs よりも高速である必要があると思います。右?
[ - - - - - - - - テスト - - - - - - - - ]
VS2010 と Intel C++ コンパイラの両方でテストを行い、結果を示しました。
struct A
{
static int s_i;
int i;
virtual void F() {i+=1;}
virtual void G() {i+=2;}
};
struct B
: public A
{
int j;
virtual void F() {i+=3;}
virtual void G() {i+=4;}
virtual void H() {i+=5;}
};
struct C
: public B
{
virtual void F() {i+=6;}
virtual void H() {i+=7;}
};
TEST(MemoryForVirtualMethod)
{
CHECK_EQUAL(sizeof(A), 8);
CHECK_EQUAL(sizeof(B), 12);
CHECK_EQUAL(sizeof(C), 12);
}
結果から、私の結論は
(1) 仮想関数を持つオブジェクトごとに、1 つの (隠しポインター) VPTR が追加されます。
(2) 各クラスに対して、クラスのすべての仮想メソッドに対して仮想メソッド テーブルが構築されます。
(3) VPTR をオブジェクトに入れるのは、参照されるクラスが動的クラスではない可能性があるため、動的ディスパッチを実装するためです。
(4) 実装は呼び出しが効率的 (手動の ifs よりも高速) ですが、一部のメモリが犠牲になります。
どうもありがとう!