Modern C++ compilers typically generate very inefficient code when virtual functions are used, particularly when there are virtual base classes.
Implementing an interface and supporting overridable methods (i.e. redefinition in derived classes) are logically distinct concepts, and therefore it is useful to separate these concerns in the programming language.
Avoiding the vtable pointer in an object is particularly beneficial for applications that record large numbers of small objects in memory. The overhead of dynamic polymorphism is only paid when needed. For example, at a given point in time there could be millions of Circle objects in memory, and only a few are being accessed by clients through an interface pointer.
Class methods are not declared virtual and therefore it is more likely that the C/C++ compiler will optimise implementations because it doesn’t commit so quickly to the indirection associated with a vtable look-up.
For example, in the following function the compiler has no need to generate a virtual call to Circle::GetArea(). This also allows it to in-line the method call - one of the most effective optimisations available to a compiler.
float64 GetConeVolume(Circle base, float64 height)
{
return base.GetArea()*height/3;
}
If Circle::GetArea() is virtual then the compiler must perform further analysis to determine whether the method has been overridden in a derived class. Since it is always possible that a derived class is defined in a different library which is dynamically loaded at run time, it is generally impossible for the compiler to avoid the overhead of the virtual call without top-down type analysis.
Interfaces support Multiple Inheritance (MI) very effectively and efficiently. If required, interfaces can form complex MI hierarchies. Also a class can support hundreds of interfaces without any negative impact on performance. Object instances never contain any vtable pointers and vtable pointers are only defined and initialised at the point where an interface pointer is required.
By contrast, using abstract base classes with complex inheritance hierarchies leads to vtable pointer bloat in most C++ compilers, particularly when using virtual base classes.
Object creation is faster because there are no vtable pointers to initialise. This has been found significant for classes using many virtual base classes with the Microsoft Visual C++ compiler.
Interfaces always specify a set of abstract method definitions, and never allow for implementation inheritance (either of member variables or implementation of member functions).
By contrast subclassing combines the notions of interface and implementation inheritance.
An object can be made to implement an interface regardless of whether its methods are declared virtual and regardless of what bases classes it derives from. One or more of the methods could even be static!
Objects can be made to implement the same interface in different ways for different purposes. An example is given below where class CDPlayer is able to implement interface IButtonListener in two distinct ways in order to distinguish the notifications it receives from its play and stop buttons.
Interfaces allow for objects to be interconnected or "wired up" without the wiring itself being heap allocated.