我一直在四处寻找这一点,对此的共同回应似乎是“它们是无关的,一个不能代替另一个”。但是说你正在接受采访并被问到“你何时会使用模板而不是继承,反之亦然?”
答案 0 :(得分:60)
我看到它的方式是模板和继承是字面上的正交概念:继承是“垂直的”并且从抽象到越来越具体。形状,三角形,等边三角形。
另一方面,模板是“水平的”,并定义了彼此不知道的代码的并行实例。排序整数与排序双精度和排序字符串正式相同,但这些是三个完全不同的函数。他们从远处“看起来”都一样,但他们彼此无关。
继承提供运行时抽象。模板是代码生成工具。
因为这些概念是正交的,所以可以愉快地将它们结合使用以实现共同的目标。我最喜欢的例子是 type erasure ,其中类型擦除容器包含一个指向实现类的虚拟基指针,但是由模板派生类生成的任意多个具体实现。模板代码生成用于填充继承层次结构。魔法。
答案 1 :(得分:19)
“常见反应”是错误的。在“有效的C ++”中,Scott Meyers在第41项中说:
迈耶斯接着总结道:第41项:理解隐式接口和编译时多态性。
- 类和模板都支持接口和多态。
- 对于类,接口是显式的并且以函数为中心 签名。多态性在运行时通过虚函数发生。
- 对于模板参数,接口是隐式的并且基于有效 表达式。在通过模板编译期间发生多态性 实例化和函数重载决策。
答案 2 :(得分:3)
如果要保留类型安全性或希望避免虚拟调度,请在基础(或合成)中使用模板。
答案 3 :(得分:1)
定义适用于多种类型的无关对象的接口时,模板是合适的。模板对于容器类非常有意义,它必须对容器中的对象进行泛化,同时保留类型信息。
在继承的情况下,所有参数必须是已定义的参数类型,或从中扩展。因此,当方法对正确具有直接层次关系的对象进行操作时,继承是最佳选择。
当继承错误地应用时,它需要创建过于复杂的类层次结构,不相关的对象。代码的复杂性将增加一小部分。如果是这种情况,请使用模板。
答案 4 :(得分:0)
模板描述了一种算法,例如决定类的两个对象之间的比较结果或对它们进行排序。正在操作的对象的类型(类)有所不同,但操作或逻辑或步骤等在逻辑上是相同的。
另一方面,子类仅用于扩展或更具体的父类功能。 希望有意义