I recently I came across a C++ interview question which got me very intrigued:
Suppose you declare mistakenly some C++ member function as virtual, but (maybe for performance reasons) you want to prevent the compiler from creating a v-table for this function. That is, disable thee dynamic function binding in favor of a static binding.
How would you achieve this? Also, are there some C++11 specific ways of doing so?
I'm aware of no way to coerce a C++ compiler to disable dynamic binding, short of forcing it to compile code purely as C if it supports such an option (which not all C++ compilers do, but most do). However, that is sort of throwing out the baby with the bathwater, as it notionally disables all C++ features that are not part of C.
There is, of course, the final
identifier introduced in C++11, which prevents further derivation from a class or overriding of virtual members. Strictly speaking, this does not prevent dynamic dispatch though - it addresses a different problem.
One way to avoid implications (perceived or actual) of dynamic binding is to avoid using or writing any classes with virtual member functions, and to not create a class hierarchy (i.e. don't derive from classes with virtual functions). Clearly, if there are no virtual functions in play, there is no need for virtual function dispatch, and therefore no need for dynamic binding.
If you know the type of an object, it is possible to avoid use of dynamic binding by using static dispatch i.e. explicitly naming which function to call. For example, let's say we have a class Base
that provides a public
virtual
member named foo()
and a class named Derived
that inherits from Base
and overrides foo()
. Then the following avoids doing dynamic dispatch;
Base *b = new Derived;
b->Base::foo(); // static call; will not call `Derived::foo()`
b->Derived::Foo(); // incorrect static call. Will not compile since b is a pointer to Base not Derived
Derived *d = new Derived;
d->Derived::foo(); // static call of Derived::foo()
d->Base::foo(); // static call of Base::foo()
Of course, if the code which uses an object relies on knowledge of the ACTUAL type of an object, or on a specific variant of foo()
being called, then its design sort-of defeats the purpose of having a polymorphic base class and other classes that derive from it.
In the above, the compiler will still support virtual function calls (vtable, etc, if that is now the compiler works) and that may affect the process of creating and destroying objects.
Another technique to avoid dynamic dispatch (or binding) is to use templates (sometimes called compile-time polymorphism). Essentially, the template may assume a type provides some interface (or set of operations) and will work with any variable of a type with that interface. For example;
struct X
{
void foo();
};
template<class T> void func()
{
T x; // relies on T being instantiable (and destructible)
x.foo(); // relies on T having a member named foo()
}
// in some function somewhere where both X and func() are known to the compiler
func<X>();
Such templates do not need the type T
to have virtual functions, so do not rely on dynamic dispatch (binding). However, there is nothing stopping such a template function working with a class that has virtual member functions, so this does not disable dynamic binding - it only allows the programmer to make choices to avoid using dynamic binding.
If I was asked this question in interview, I'd probably point out all of the above, but leave it unsaid that the question is rather silly. An interviewer knowledgeable about C++ will realise that, and just be interested in how you think through and address such a question (after all real-world developers are often asked by management or customers to meet silly or unrealistic requirements, and are expected to be tactful enough to avoid telling their managers or customers they are being foolish). If the interviewer has asked the question without understanding that (or without another member of the interview panel who understands that in the room) I wouldn't want to work with that employer anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With