1

virtual function基本クラスのaがnot overriden派生クラスにある場合を考えてみます。次にbase class pointer to a derived class object、仮想関数を使用して呼び出されます。

関数の呼び出しは、コンパイル時に基本クラスの関数に解決されることを理解しています。

質問

関数は派生クラスでオーバーライドされないため、関数呼び出しはコンパイル時に関数実装にバインドされますか、それとも実行時までバインドを遅らせますか?

4

2 に答える 2

1

ほとんどの場合、コンパイル時に解決されます。
現代のコンパイラのほとんどは、コンパイル時に動的ディスパッチを解決するのに十分な信頼できる情報があれば、それを解決するのに十分なほど賢いです。
この場合、Derivedクラスにはオーバーライド関数が提供されていないため、スマートコンパイラはコンパイル時に静的に関数呼び出しを解決できるはずです。

于 2012-01-25T06:29:28.970 に答える
1

To be able to guess the implementation at compile time the compiler must know the type of the pointed to object... for example

MyBaseClass *p = new MyDerivedClass;
p->foo();

In the above a compiler should be smart enough to guess the type of the pointed-to object and the dispatching (assuming the compiler is using the VMT solution for late binding) should require no VMT lookup even if the method is virtual.

However for example in the following

void doit(MyBaseClass *p)
{
    p->foo();
    ...
}

the code for doit cannot know the type of the object pointed to and therefore the call will require a VMT lookup. Note that the C++ language has been designed so that compilers can work one compilation unit at a time, therefore there is no way the compiler can know that there is for example only one derived type in your program (the source code of another module could define a different derived class, even in a local unnamed namespace, where the function is overridden).

Of course the function doit could end up being inlined by the compiler and so a specific call site invoking doit could indeed require no lookup if the type can be inferred. But if the doit function is publically visible (e.g. it's not in the unnamed namespace or a static free function) then the machine code generated for it will include a VMT lookup when called from other complation units.

Note that in all this discussion about when a lookup is needed or not is totally irrelevant if the virtual function has been overridden or not. The reason is that if a virtual function has not been overridden and the dispatching is implemented with VMTs then simply the derived class VMT will have in that slot the address of the base implementation.

In other words what happens is that p->foo() is compiled as either

 p->__VMT__[__FOO_VMT_SLOT_NUMBER__](p);  // Dynamic dispatch

or

 __DERIVED_FOO_IMPLEMENTATION__(p); // Type known at compile time

where __DERIVED_FOO_IMPLEMENTATION__ is the function pointer stored in the VMT and it may be equal to the address of the base implementation or not depending on if the function has been overridden in the derived class.

于 2012-01-25T07:27:02.150 に答える