1. C++类模板:从基础到实战的全面解析
在C++编程中,类模板(Class Template)是泛型编程的核心工具之一。它允许我们编写与数据类型无关的代码,极大地提高了代码的复用性和灵活性。作为一名长期使用C++进行开发的工程师,我发现类模板在实际项目中能显著减少重复代码量,特别是在开发容器类、算法库和跨平台组件时尤为有用。
类模板的基本思想很简单:定义一个可以接受不同类型参数的类。编译器会根据实际使用的类型自动生成对应的具体类代码。这种机制使得我们可以用同一套逻辑处理不同类型的数据,而无需为每种类型都重写一遍相似的代码。比如STL中的vector、list等容器都是通过类模板实现的。
2. 类模板的基本语法与使用
2.1 类模板的声明与定义
类模板的基本语法如下:
cpp复制template <typename T>
class MyTemplateClass {
// 类成员声明和定义
};
这里的typename T表示模板参数,T是一个占位符类型,在实例化类模板时会被实际类型替换。也可以使用class关键字代替typename,两者在大多数情况下是等价的:
cpp复制template <class T>
class MyTemplateClass {
// 类成员声明和定义
};
一个完整的类模板示例:
cpp复制template <typename T>
class Box {
private:
T content;
public:
void setContent(const T& newContent) {
content = newContent;
}
T getContent() const {
return content;
}
};
2.2 类模板的实例化
使用类模板时,需要指定具体的类型参数:
cpp复制Box<int> intBox; // 创建一个存储int的Box
Box<std::string> strBox; // 创建一个存储string的Box
编译器会根据我们提供的类型参数生成对应的具体类。这个过程称为模板实例化。
注意:模板代码只有在被实例化时才会真正编译。如果模板代码有错误,但从未被实例化使用,编译器可能不会报错。
2.3 类模板的成员函数定义
类模板的成员函数可以在类内部定义(隐式内联),也可以在类外部定义。外部定义时需要加上模板前缀:
cpp复制template <typename T>
class Box {
T content;
public:
void setContent(const T& newContent);
T getContent() const;
};
// 外部定义成员函数
template <typename T>
void Box<T>::setContent(const T& newContent) {
content = newContent;
}
template <typename T>
T Box<T>::getContent() const {
return content;
}
3. 类模板的高级特性
3.1 多模板参数
类模板可以接受多个类型参数:
cpp复制template <typename T, typename U>
class Pair {
T first;
U second;
public:
Pair(const T& f, const U& s) : first(f), second(s) {}
T getFirst() const { return first; }
U getSecond() const { return second; }
};
使用示例:
cpp复制Pair<int, std::string> student(123, "Alice");
3.2 默认模板参数
可以为模板参数指定默认值:
cpp复制template <typename T = int, int size = 10>
class Array {
T data[size];
// ...
};
使用时可省略有默认值的参数:
cpp复制Array<> arr1; // 使用默认的int和10
Array<double> arr2; // T=double, size=10
Array<double, 20> arr3;
3.3 模板特化
当需要对特定类型进行特殊处理时,可以使用模板特化:
cpp复制// 通用模板
template <typename T>
class Printer {
public:
void print(const T& value) {
std::cout << "Generic: " << value << std::endl;
}
};
// 对const char*类型的特化
template <>
class Printer<const char*> {
public:
void print(const char* value) {
std::cout << "Specialized for strings: " << value << std::endl;
}
};
3.4 非类型模板参数
除了类型参数,模板还可以接受非类型参数(如整型、指针等):
cpp复制template <typename T, int size>
class FixedArray {
T data[size];
public:
T& operator[](int index) {
if (index < 0 || index >= size) {
throw std::out_of_range("Index out of range
