[基础]详解C++模板类(完整实例代码)
目录
- C++模板类:通用编程的基石
- 引言
- 一、模板类的核心作用
- 1.1 代码复用
- 1.2 类型安全
- 1.3 性能优化
- 二、模板类的进阶用法
- 2.1 多参数模板
- 2.2 非类型参数
- 2.3 成员函数特化
- 三、实战场景解析
- 3.1 场景一:通用容器开发
- 3.2 场景二:算法抽象
- 3.3 场景三:资源管理
- 四、可运行案例:智能指针实现
- 4.1 基础框架
- 4.2 防止拷贝
- 4.3 移动语义支持
- 4.4 使用演示
- 五、最佳实践与注意事项
- 5.1 分离编译问题
- 5.2 显式实例化
- 5.3 SFINAE应用
- 六、模板元编程初探
- 结语
C++模板类:通用编程的基石
引言
在C++开发中,我们经常会遇到这样的困境:如何编写既能处理int
又能处理std::string
的通用类?传统的面向对象编程通过虚函数和基类指针虽然能实现一定通用性,但存在类型安全风险和性能损耗。C++模板类正是为解决这类问题而生,它让代码像乐高积木一样具备"泛型"能力。
一、模板类的核心作用
1.1 代码复用
通过模板参数化类型,一套逻辑可以适配所有类型:
template<typename T>
class Box {T item;
public:Box(T i) : item(i) {}T getItem() { return item; }
};
这个简单的盒子类可以存储任何类型,避免了为每个类型重复编写类定义。
1.2 类型安全
不同于void*
的野蛮类型转换,模板在编译期进行类型检查:
Box<int> intBox(42);
int value = intBox.getItem(); // 安全无转换
1.3 性能优化
模板实例化发生在编译期,避免了运行时多态的虚函数调用开销:
// STL的std::vector<int>完全内联优化后
// 性能甚至超过手写数组
二、模板类的进阶用法
2.1 多参数模板
支持定义多个类型参数:
template<typename Key, typename Value>
class HashMap {// 实现键值对存储
};
2.2 非类型参数
除了类型,还可以传递常量值:
template<typename T, int Size>
class StaticArray {T data[Size];
public:T& operator[](int i) { if(i >= Size) throw std::out_of_range();return data[i]; }
};
2.3 成员函数特化
可以针对特定类型定制实现:
template<>
std::string Box<std::string>::getItem() {return "\"" + item + "\""; // 添加引号
}
三、实战场景解析
3.1 场景一:通用容器开发
需求:实现跨平台内存池
方案:
template<typename T, size_t BlockSize = 4096>
class MemoryPool {char memoryBlock[BlockSize];// 实现对象池化管理
};
3.2 场景二:算法抽象
需求:不同加密算法接口统一
方案:
template<typename CipherT>
class CryptoWrapper {
public:void encrypt(const void* in, void* out) {cipher.doEncrypt(in, out);}
private:CipherT cipher;
};
3.3 场景三:资源管理
需求:数据库连接池
方案:
template<typename ResourceT, typename PoolT = DefaultPool>
class ResourceManager {PoolT pool;
public:ResourceT* get() { return pool.acquire(); }
};
四、可运行案例:智能指针实现
4.1 基础框架
template<typename T>
class UniquePtr {T* ptr;
public:explicit UniquePtr(T* p = nullptr) : ptr(p) {}~UniquePtr() { delete ptr; }T& operator*() { return *ptr; }T* operator->() { return ptr; }
};
4.2 防止拷贝
// C++11禁用拷贝构造
UniquePtr(const UniquePtr&) = delete;
UniquePtr& operator=(const UniquePtr&) = delete;
4.3 移动语义支持
// C++11右值引用
UniquePtr(UniquePtr&& other) noexcept : ptr(other.ptr) {other.ptr = nullptr;
}
4.4 使用演示
struct Test {void hello() { std::cout << "Hello Templates!\n"; }
};int main() {UniquePtr<Test> ptr(new Test());ptr->hello();return 0;
}
// 输出:Hello Templates!
五、最佳实践与注意事项
5.1 分离编译问题
模板实现必须放在头文件:
// Array.hpp
template<typename T>
class DynamicArray {// 实现代码
};
5.2 显式实例化
对于常用类型提前实例化可加速编译:
template class DynamicArray<int>; // 在cpp文件中
5.3 SFINAE应用
通过启用/禁用特性实现条件编译:
template<typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
isEven(T x) { return x % 2 == 0; }
六、模板元编程初探
模板不仅能泛化类型,还能做编译期计算:
template<int N>
struct Factorial {enum { value = N * Factorial<N-1>::value };
};template<>
struct Factorial<0> {enum { value = 1 };
};int main() {std::cout << Factorial<5>::value; // 输出120
}
结语
模板类是C++实现泛型编程的核心武器,从STL容器到现代C++并发库,无不闪耀着模板的智慧光芒。掌握模板类不仅能让代码更简洁高效,更能培养程序员抽象建模的能力。建议读者从改造现有重复代码开始,逐步将模板技术融入日常开发实践。