58

I've been looking around for this one, and the common response to this seems to be along the lines of "they are unrelated, and one can't be substituted for the other". But say you're in an interview and get asked "When would you use a template instead of inheritance and vice versa?"

Mat
  • 202,337
  • 40
  • 393
  • 406
Brent212
  • 1,835
  • 4
  • 19
  • 23
  • 34
    How is this "not a real question"? Close-happy trigger fingers irritate me. – Lightness Races in Orbit Aug 31 '11 at 23:20
  • 2
    If you hear this question in an interview, it's time to say goodbye, since they are just wasting your time; and you now do the same with ours. – Gene Bushuyev Aug 31 '11 at 23:21
  • 2
    It's a dumb interview question. At best, it's the wrong way around. You should not ask "when do you use tool X". You should ask, "here's problem J. How do you solve it?" and the answer may be "tool X". – tenfour Aug 31 '11 at 23:34
  • 19
    This is actually a great question. It tests the programmers ability to think abstractly about classes of problems rather than being "given" a problem. Upon finding this question it was clear exactly what was being asked, and was not vague in the slightest. Second Lightness Races in Orbit statement. Trigger-happy closing is borderline trolling. – optikradio Mar 07 '13 at 23:28
  • 1
    Possible duplicate of [c++ standard practice: virtual interface classes vs. templates](https://stackoverflow.com/questions/1165963/c-standard-practice-virtual-interface-classes-vs-templates) – Trevor Boyd Smith Jun 15 '18 at 12:42
  • 1
    This question boils down to the following: which is the right mental model for polymorphism, generalization or refinement? Human brains works in the way that it always starts from concrete examples, and then goes to the next abstract level by generalization. – John Z. Li Sep 11 '18 at 03:23

5 Answers5

93

The way I see it is that templates and inheritance are literally orthogonal concepts: Inheritance is "vertical" and goes down, from the abstract to the more and more concrete. A shape, a triange, an equilateral triangle.

Templates on the other hand are "horizontal" and define parallel instances of code that knowns nothing of each other. Sorting integers is formally the same as sorting doubles and sorting strings, but those are three entirely different functions. They all "look" the same from afar, but they have nothing to do with each other.

Inheritance provides runtime abstraction. Templates are code generation tools.

Because the concepts are orthogonal, they may happily be used together to work towards a common goal. My favourite example of this is type erasure, in which the type-erasing container contains a virtual base pointer to an implementation class, but there are arbitrarily many concrete implementations that are generated by a template derived class. Template code generation serves to fill an inheritance hierarchy. Magic.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 2
    I like this explanation. It's a little more in plain english than the others. – Brent212 Sep 02 '11 at 05:13
  • 1
    Hmm, I'm not an expert in the matter and that's why I found this answer, but as you describe it, it seems to me that templates solve the lack of C++ for a complex inherence system like mixins (a problem, for instance, solved elegantly by Go). If ints and doubles and strings have nothing in common but need to be sorted, all three should extend in some way a "Sortable" trait. – pistacchio Apr 04 '14 at 07:54
  • 2
    @pistacchio: I wouldn't call complex inheritance a "solution". Templates provide sortability in a much nicer way, since the sortee doesn't need to know that it's being sorted. Complex inheritance typically results when you work with a forced mindset that everything must be an inheritance hierarchy, which is in fact rarely appropriate. Go's approach is simple, but more restrictive and less efficient. It's appropriate for the small language Go wants to be. – Kerrek SB Apr 04 '14 at 08:34
  • I want to challenge this. You're describing abstraction, which is simply parameterizing the dissimilar behavior. With templates, the parameter is evaluated statically, with inheritance, it's evaluated dynamically (you could envision a pure virtual interface 'Sortable'--of course, in C++, primitives can't satisfy interfaces, so you need to do some boxing to sort ints and the like, but this has nothing to do with inheritance (rather, the limitation was introduced by C++'s implementation of inheritance). Also worth noting: 'inheritance' is probably a bad term; we should be saying 'polymorphism'. – weberc2 Apr 24 '15 at 15:13
  • @KerrekSB Go's approach doesn't require the sortee to know what is being sorted either; for example, time.Time doesn't know that it is sortable, but it provides a 'Before' method (akin to 'less()'), so it is sortable. Templates are usually nicer for something like sorting because runtime polymorphism typically implies a small runtime cost per element, but sorting usually takes place on large data sets, so this small runtime cost becomes larger. Sorting is a bad example for the template vs runtime-polymorphism conversation. – weberc2 Apr 24 '15 at 15:20
26

The "common response" is wrong. In "Effective C++," Scott Meyers says in Item 41:

Item 41: Understand implicit interfaces and compile-time polymorphism.

Meyers goes on to summarize:

  • Both classes and templates support interfaces and polymorphism.
  • For classes, interfaces are explicit and centered on function signatures. Polymorphism occurs at runtime through virtual functions.
  • For template parameters, interfaces are implicit and based on valid expressions. Polymorphism occurs during compilation through template instantiation and function overloading resolution.
Gnawme
  • 2,321
  • 1
  • 15
  • 21
  • 1
    Does he make the typo, too? :P – Lightness Races in Orbit Aug 31 '11 at 23:20
  • I advise everybody to go read that chapter, it will be clear what you need to use from the introduction :) – Hame Dec 27 '14 at 15:26
  • 2
    In the first edition of Effective C++, the most relevant section is Item 42: "Differentiate between inheritance and templates". Item 41 in that book is "Use private inheritance judiciously". Just mentioning this to anyone who has that edition. – Alan Apr 19 '17 at 15:51
  • 3
    this explains what they are but doesn't help you decide which one to use. – MK. Jun 07 '17 at 15:28
  • 1
    @MK. It at least tells you that if you need dynamic polymorphism you need virtual methods, whereas if you only need static polymorphism (to make coding easier and write generic code as opposed to dealing with generic input) then templates/concepts are also an option. – pooya13 Jun 16 '20 at 20:59
  • @pooya13 your comment is actually helpful. – MK. Jun 17 '20 at 05:22
4

use a template in a base (or composition) when you want to retain type safety or would like to avoid virtual dispatch.

justin
  • 104,054
  • 14
  • 179
  • 226
  • 4
    Indeed, I suspect avoiding virtual dispatch via [CRTP](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) is what the interviewer was looking for. – ildjarn Aug 31 '11 at 23:05
2

Templates are appropriate when defining an interface that works on multiple types of unrelated objects. Templates make perfect sense for container classes where its necessary generalize the objects in the container, yet retain type information.

In case of inheritance, all parameters must be of the defined parameter type, or extend from it. So when methods operate on object that correctly have a direct hierarchical relationship, inheritance is the best choice.

When inheritance is incorrectly applied, then it requires creating overly complex class hierarchies, of unrelated objects. The complexity of the code will increase for a small gain. If this is the case, then use templates.

cmcginty
  • 113,384
  • 42
  • 163
  • 163
0

Template describes an algorithm like decide the result of a comparison between the two objects of a class or sorting them. The type(class) of objects being operated on vary but the operation or logic or step etc is logically the same.

Inheritance on the other hand is used by the child class only to extend or make more specific the parents functionality. Hope that makes sense