1 & 2) 「シンボル テーブル」からオブジェクトの型を取得する必要はありません。v-table は通常、オブジェクトの非表示フィールドによってポイントされます。したがって、v-table の取得は基本的に 1 つのポインター間接化です。
3) v-table は「検索」されません。各仮想関数には、コンパイル時に決定される v-table 内の固定インデックス/オフセットがあります。したがって、これは基本的にポインターからのオフセットからのフェッチです。
したがって、直接の C スタイルの呼び出しよりも遅くなりますが、あなたが提案するほど難しくはありません。これは、C の次のようなものに似ています。
struct MyObject_vtable {
int (*foo)();
void (*bar)(const char *arg);
};
struct MyObject {
int m_instanceVariable1;
int m_instanceVariable2;
struct MyObject_vtable *__vtable;
};
struct MyObject * obj = /* ... construct a MyObject instance */;
// int result = obj->foo();
int result = (*(obj->__vtable.foo))();
// obj->bar("Hello");
(*(obj->__vtable.bar))("Hello");
また、これは質問の範囲を少し超えているかもしれませんが、多くの場合、コンパイラーはコンパイル時に呼び出される関数を決定できることに注意してください。そのような場合、関数を直接呼び出すことができます。仮想呼び出し機構。例えば:
MyObject obj1;
int result1 = obj1.foo();
MyObject *obj2 = getAMyObject();
int result2 = obj2->foo();
foo()
この場合、最初の呼び出しでどちらを呼び出すかはコンパイル時にわかっているため、直接呼び出すことができます。2 番目の呼び出しでは、が をオーバーライドgetAMyObject()
した派生クラスのオブジェクトを返す可能性があるため、仮想呼び出しメカニズムを使用する必要があります。MyObject
foo()