Sermons

"Joshua did steep his wax in sheeps' blood; should we not repent our misgivings?" (Sot 45:2)


Templates versus virtual functions


Virtual functions and templates offer polymorphic features. The primary way to think about the difference is that templates offer compile-time polymorphism and virtual functions offer run-time polymorphism.

Neither is without overhead and these overheads need to be understood if they are to be used efficiently.

A parametized generated template function should have no more overhead than a normal function in the final executable. However, a complete new parametized copy of the function is added to the executable for each new type, including derived types, that call the function. If a large template function is called with many different types the overall size of the executable will increase. This is rarely of significance in modern computing but it is worth bearing in mind.

If a template function or one of its users changes then the template and all the users have to be recompiled. This is not always possible.

Virtual functions have slightly more complex overheads than templates. Each instance of an object with one or more virtual functions has an 'natural' sized pointer in addition to its data members. Each class with one or more virtual functions has a virtual function table (vtable) to which the pointers point.

When a virtual function is called the computer must get the vtable pointer from the object (which must itself be indirect in most cases), get hold of the vtable (with the potential for regular page faults on some systems), offset into it to find the function pointer and then finally indirectly call the function via the pointer from the vtable. Again, this is rarely significant in modern code.

Virtual functions cannot be easily inlined. However, if either a virtual function or a user of one changes, the other need not be recompliled. Modern operating systems can supply an abstract base class for an application. The programmer derives his application from this base and provids the operations. Operating system object code can now interact with the programmer's object code without recompilation.

Given that the overheads in each case are unlikely to be significant, when should one use one or the other? A class derived from a virtual interface must supply or rely upon the virtual interface for any operation, or indeed to compile. Objects handed to template functions need only supply the operations used by that function in order for it to work. If their is a tight relationship between all the objects using a function, the virtual function mechanism helps to make this explicit in code and will generate less assembly. Template functions impose no relationship upon objects using them other than that they all suppot certain operations.

Importantly, especially from the point of view of the standard library, built-types can be used as parameters to template functions.