何时使用模板而不是派生类

When to use templates rather than derived classes

本文关键字:派生 何时使      更新时间:2023-10-16

除了简化的通用算法之外,模板相对于类层次结构还有什么好处吗?例如,在类层次结构上使用模板是否更有效?模板作为金融工具受到程序员的高度赞扬,但我真的不明白为什么。

模板与类层次结构

主要是虚拟函数调用的成本。如果函数的实际工作的计算成本很小,那么虚拟调度的成本可能很大。与内联函数相比,如果在紧密循环中使用,情况尤其如此。使用运行时多态性排除了函数内联的可能性。

C++模板是一个非常强大的工具

除了C++标准库中常见的通用容器和算法外,C++模板还支持一系列高级技术,如:

  • 基于策略的设计
  • 模板元编程

从本质上讲,您正在对编译器进行编程,以构建所需的类。如果使用得当,这可以提供高度可重用的最佳代码。如果误用,它可能会给出比更合适的方法更臃肿的对象代码。

当需要速度时,我们使用模板而不是运行时动态多态性,并且模板可能提供编译时多态性(在编译时解决),而没有虚拟方法查找开销。

来自维基百科:

多态性是一种常见的标准编程工具对象可以用作其基础对象的实例,但是将调用派生对象的方法,其中虚拟方法将是派生类最多的方法。这动态多态行为(通常)通过用虚拟方法为类创建虚拟查找表,在运行时遍历的表,以标识要执行的方法调用。因此,运行时多态性必然需要执行开销(尽管在现代建筑中,开销可以忽略不计)。然而,在许多情况下,所需的多态行为是不变的并且可以在编译时确定。然后奇怪地重复模板模式(CRTP)可以用于实现静态多态性,这是对编程代码中多态性的模仿,但在编译时解析,从而取消运行时虚拟表查找。


另一个例子是模板在编译时计算的能力,例如众所周知的阶乘,通常像一样编写

unsigned int factorial(unsigned int n) {
  return (n==0)? 1 : n * factorial(n-1); 
}
const int x = factorial(4); // == (4 * 3 * 2 * 1 * 1) == 24
const int y = factorial(0); // == 0! == 1 

是在运行时计算的。但是使用模板编写

template <int N>
struct Factorial {
    enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0> {
    enum { value = 1 };
};
// Factorial<4>::value == 24
// Factorial<0>::value == 1
const int x = Factorial<4>::value; // == 24
const int y = Factorial<0>::value; // == 1

是在编译时计算的,没有强加任何运行时开销。