Previously we looked at template class syntax and semantics. In this article we’ll extend this to look at inheritance of template classes.
Inheriting from a template class
It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply.
If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
Notice that we ‘pass-down’ the template parameter from the derived class to the base class since there is no class Base, only class Base<T>. The same holds true if we wish to explicitly call a base class method (in this example, the call to Base<T>::set())
We can use this facility to build generic versions of the Class Adapter Pattern – using a derived template class to modify the interface of the base class.
Notice, in this case we use private inheritance. This hides the base class methods to any clients (but keeps them accessible to the derived class. Calls to the Adapter’s methods are forwarded on to the base class. For more on the Adapter Pattern see this article.
Extending the derived class
The derived class may itself have template parameters. Please note there must be enough template parameters in the derived class to satisfy the requirements of the base class.
Specialising the base class
The derived class may also specialise the base class. In this case we are creating an explicit instance of the base class for all versions of the derived class. That is, all derived class instances, regardless of the type used to instantiate them, will have a base class with a data object of type int.
Deriving from a non-template base class
There is no requirement that your base class be a template. It is quite possible to have a template class inherit from a ‘normal’ class.
This mechanism is recommended if your template class has a lot of non-template attributes and operations. Instead of putting them in the template class, put them into a non-template base class. This can stop a proliferation of non-template member function code being generated for each template instantiation.
So far, we have been inheriting explicitly from another (base) class, but there is no reason why we can’t inherit from a template type instead – with the (reasonably obvious) requirement that the template parameter must be a class type. This mechanism allows some neat facilities to be implemented.
In the example below we have built a template class, Named. The class allows a name (string) to be prepended to any class, with the proviso that the base class (the template parameter) supports the member function display().
In this example we have constructed a normal class, Waypoint, which supports the display() method (presumably, this displays the current coordinates of the Waypoint; but who knows…).
When we create a Named object, we give it the type of the object we want to ‘decorate’ with a name (in this case, a Waypoint). Calling display() on a Named object will cause it to output the object’s name, before calling display on its base class – in our example Waypoint::display().
(NOTE: I’m quite deliberately ignoring the ‘Elephant in the Room’ with this code – how to generically construct a base class object with a non-default constructor. I’ll revisit this example again in the future when we look at Variadic Templates.)
This time we’ve covered most of the basic inheritance patterns for templates. Next time we’ll have a look at a practical application for templates in your application code.
Latest posts by Glennan Carnie (see all)
- Technical debt - August 22, 2018
- Your handy cut-out-and-keep guide to std::forward and std::move - April 26, 2018
- Setting up Sublime Text to build your project - April 12, 2018