您可以将 C++ 模板视为一种伪装成泛型系统的解释型函数式编程语言。如果这不吓到你,它应该:)
C# 泛型非常受限;您可以在一个或多个类型上参数化一个类,并在方法中使用这些类型。因此,以MSDN 为例,您可以这样做:
public class Stack<T>
{
T[] m_Items;
public void Push(T item)
{...}
public T Pop()
{...}
}
现在您可以声明Stack<int> 或Stack<SomeObject>,它会安全地存储该类型的对象(即,不用担心错误地输入SomeOtherObject)。
在内部,.NET 运行时会将其专门化为 int 等基本类型的变体和对象类型的变体。例如,这允许Stack<byte> 的表示比Stack<SomeObject> 的表示小得多。
C++ 模板允许类似的用途:
template<typename T>
class Stack
{
T *m_Items;
public void Push(const T &item)
{...}
public T Pop()
{...}
};
乍一看,这看起来很相似,但有一些重要的区别。首先,不是每个基本类型都有一个变体,而所有对象类型都有一个变体,每个实例化的类型都有一个变体。那可以是很多类型!
下一个主要区别是(在大多数 C++ 编译器上)它将在使用它的每个翻译单元中编译。这会大大减慢编译速度。
C++ 模板的另一个有趣的属性是它们可以应用于类以外的东西——当它们被应用时,它们的参数可以被自动检测到。例如:
template<typename T>
T min(const T &a, const T &b) {
return a > b ? b : a;
}
类型 T 将由函数使用的上下文自动确定。
这些属性可以用来取得好成绩,但会牺牲你的理智。因为 C++ 模板针对它所针对的每种类型重新编译,并且模板的实现始终可供编译器使用,所以 C++ 可以对模板进行非常积极的内联。再加上函数中模板值的自动检测,您可以在 C++ 中使用boost::lambda 生成anonymous pseudo-functions。因此,像这样的表达式:
_1 + _2 + _3
产生一个具有 严重可怕 类型的对象,它有一个 operator() 将其参数相加。
C++ 模板系统还有很多其他的阴暗角落——它是一个非常强大的工具,但考虑起来可能会很痛苦,而且有时很难使用——尤其是当它给你一个长达 20 页的错误消息时。 C# 系统要简单得多 - 功能较弱,但更易于理解且更难滥用。