模板
模板是C++中实现泛型编程的工具,允许编写与数据类型无关的通用代码。
函数模板
函数模板为函数提供一种方式,使其能够接受任何类型的参数。
定义
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
template 声明了模板的类型参数 T,可以是任何类型。
max 函数可以接受任何类型的两个参数,并返回两者中较大的一个。
使用
int i = max(1, 2); // 调用 int 类型的 max
double d = max(1.2, 3.4); // 调用 double 类型的 max
类模板
类模板允许你定义一个类,它的行为和数据成员与多个类型兼容。
定义
template <typename T>
class Stack {
private:
T* elements;
size_t size;
size_t capacity;
public:
Stack(size_t cap) : size(0), capacity(cap), elements(new T[capacity]) {}
~Stack() { delete[] elements; }
// 其他成员函数...
};
template 声明了类模板 Stack 的类型参数 T。
Stack 类有一个指向类型 T 的指针 elements,它存储栈的元素。
使用
Stack<int> intStack(10); // 创建一个 int 类型的 Stack
Stack<double> doubleStack(20); // 创建一个 double 类型的 Stack
模板参数
模板参数可以是类型(typename 或 class),也可以是常量表达式(template <const int N>)。
类型参数
template <typename T, typename U>
class Pair {
T first;
U second;
public:
Pair(const T& a, const U& b) : first(a), second(b) {}
};
非类型参数
template <int N>
class Array {
int data[N];
public:
// ...
};
Array<10> myArray; // 创建一个具有10个整数的数组
std::cout << "Array size: " << myArray.size() << std::endl;
这个10是编译时确认的,不用运行时申请,故而速度更快。
模板特化
模板特化是为特定类型或值提供特定实现的一种方式。
全特化 (Full Specialization)
全特化是为一个具体类型提供一个完整的类或函数模板实现。全特化覆盖了模板定义中的所有类型参数。
示例:全特化类模板
template <typename T>
class Stack {
public:
// 一些通用的模板实现
};
// 全特化Stack类模板,仅适用于double类型
template <>
class Stack<double> {
public:
void specialFunctionForDouble() {
// 针对double类型实现的特定功能
}
};
在这个例子中,Stack 是全特化的版本,它只适用于 double 类型,并且可以包含特定于 double 类型的方法,如 specialFunctionForDouble。
偏特化 (Partial Specialization)
偏特化允许你为模板的一个或多个参数提供特定的类型,同时保留其他参数的通用性。这在你需要针对某个特定类型的部分实现时非常有用。
示例:偏特化类模板
template <typename T, typename Allocator = std::allocator<T>>
class Vector {
public:
// 通用的模板实现
};
// 偏特化Vector类模板,仅适用于指针类型
template <typename T>
class Vector<T*> {
public:
void specialFunctionForPointers() {
// 针对指针类型实现的特定功能
}
};
// 也可以为多个参数提供偏特化
template <typename T>
class Vector<T, std::allocator<T*>> {
public:
void specialFunctionForPointersWithAllocator() {
// 针对特定分配器的指针类型实现的特定功能
}
};
在这个例子中,Vector<T*> 是一个偏特化版本,它适用于所有指针类型的 T。这意味着无论 Allocator 是什么,只要 T 是指针类型,就会使用这个偏特化版本。此外,还有一个针对特定分配器的偏特化版本 Vector<T, std::allocator<T*>>。
注意事项:
全特化和偏特化必须在模板定义的外部声明。
全特化使用 template <> 明确指出不需要任何类型参数。
偏特化则在 template (或其他参数)后面提供具体的类型或类型模式。
偏特化可以与非类型模板参数结合使用,为特定的常量值提供特化。
模板的优缺点
优点
类型安全:模板代码在编译时类型检查。
性能:没有运行时开销,因为所有类型都是在编译时确定的。
通用性:同一份代码可以用于不同的数据类型。
缺点
编译时间:模板代码可能导致编译时间变长。
错误信息:模板错误可能难以调试和理解。
二进制兼容性:不同的编译单元可能无法共享模板实例。
模板是C++中强大的特性,允许编写灵活、高效的通用代码。但它们也需要仔细设计和使用,以避免潜在的问题。