// 在头文件中声明并定义模板类 template <typename T> class Calculator { public: // 成员函数声明与定义 T add(T a, T b) { return a + b; } T multiply(T a, T b) { return a * b; } };
二、模板参数推导机制
2.1 模板参数类型
类模板可以接受多种类型的参数:
类型参数(typename T 或 class T)
非类型参数(常量表达式)
模板模板参数(以模板作为参数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 包含多种参数类型的类模板 template <typename T, int Size, template <typename> class Container> class Buffer { private: Container<T> data; public: void fill(T value) { for (int i = 0; i < Size; ++i) { data.push_back(value); } } };
// 使用示例 Buffer<int, 10, std::vector> intBuffer;
2.2 模板参数推导规则
C++17 引入了类模板参数推导 (CTAD),允许编译器从构造函数的参数推导出模板参数类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
template <typename T> class Pair { public: T first; T second; Pair(T a, T b) : first(a), second(b) {} };
// C++17之前需要显式指定类型 Pair<int> p1(1, 2);
// C++17及以后可以自动推导 Pair p2(3, 4); // 推导出Pair<int>
对于模板模板参数,需要显式指定,无法自动推导:
1 2 3 4 5 6 7 8 9 10
template <typename T, template <typename> class Container> class Wrapper { public: Container<T> items; Wrapper(std::initializer_list<T> list) : items(list) {} };
// 通用模板 template <typename T, typename U> class Pair { public: T first; U second; Pair(T a, U b) : first(a), second(b) {} };
// 偏特化:当两个类型相同时 template <typename T> class Pair<T, T> { public: T first; T second; Pair(T a, T b) : first(a), second(b) {} // 额外的方法,仅适用于两个类型相同的情况 bool areEqual() const { return first == second; } };
template <typename T> class DynamicArray { private: T* data; size_t size; size_t capacity; void resize() { capacity *= 2; T* newData = new T[capacity]; for (size_t i = 0; i < size; ++i) { newData[i] = data[i]; } delete[] data; data = newData; } public: // 构造函数 DynamicArray() : size(0), capacity(1) { data = new T[capacity]; } // 析构函数 ~DynamicArray() { delete[] data; } // 添加元素 void push_back(const T& element) { if (size >= capacity) { resize(); } data[size++] = element; } // 获取元素 T& operator[](size_t index) { if (index >= size) { throw std::out_of_range("Index out of bounds"); } return data[index]; } // 获取大小 size_t getSize() const { return size; } };
// 使用示例 DynamicArray<std::string> stringArray; stringArray.push_back("First"); stringArray.push_back("Second"); for (size_t i = 0; i < stringArray.getSize(); ++i) { std::cout << stringArray[i] << std::endl; }
五、常见问题解决方案
5.1 模板实例化错误
模板实例化错误通常表现为复杂的编译错误信息,解决方法是:
检查模板参数是否满足所有隐含要求
使用 static_assert 提供更清晰的错误信息
逐步简化代码定位问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
template <typename T> class MathOperations { public: // 确保T支持除法运算 static T divide(T a, T b) { static_assert(std::is_arithmetic<T>::value, "MathOperations requires arithmetic types"); if (b == 0) { throw std::invalid_argument("Division by zero"); } return a / b; } };