当前位置: 首页 > news >正文

C++笔记(面向对象)类模板

1. 类模板的基本概念

什么是类模板?

类模板是能够根据不同数据类型生成不同类的"蓝图"。

生活比喻:

text

做饼干的模具:
- 同一个模具,可以用面粉做饼干
- 也可以用巧克力做饼干  
- 模具是模板,具体的饼干是实例化的类

2. 基本语法

2.1 最简单的类模板

cpp

#include <iostream>// 声明类模板
template<typename T>  // T 是类型参数
class Box {
private:T content;public:Box(const T& item) : content(item) {}T getContent() const {return content;}void setContent(const T& item) {content = item;}void show() const {std::cout << "Box contains: " << content << std::endl;}
};

2.2 使用类模板

cpp

void basicTemplateDemo() {std::cout << "=== 基本类模板使用 ===" << std::endl;// 实例化为 int 类型Box<int> intBox(42);intBox.show();// 实例化为 double 类型Box<double> doubleBox(3.14);doubleBox.show();// 实例化为 string 类型Box<std::string> stringBox("Hello Template!");stringBox.show();
}

3. 多参数类模板

3.1 多个类型参数

cpp

template<typename T1, typename T2>
class Pair {
private:T1 first;T2 second;public:Pair(const T1& f, const T2& s) : first(f), second(s) {}T1 getFirst() const { return first; }T2 getSecond() const { return second; }void setFirst(const T1& f) { first = f; }void setSecond(const T2& s) { second = s; }void display() const {std::cout << "Pair: (" << first << ", " << second << ")" << std::endl;}
};void multiParamDemo() {std::cout << "\n=== 多参数类模板 ===" << std::endl;Pair<int, std::string> student(1001, "Alice");student.display();Pair<std::string, double> product("Apple", 5.99);product.display();Pair<int, Pair<int, std::string>> nested(1, Pair<int, std::string>(2, "Nested"));nested.display();
}

3.2 非类型模板参数

cpp

template<typename T, int Size>
class FixedArray {
private:T data[Size];public:FixedArray() {for (int i = 0; i < Size; ++i) {data[i] = T();  // 默认值}}T& operator[](int index) {if (index < 0 || index >= Size) {throw std::out_of_range("Index out of range");}return data[index];}const T& operator[](int index) const {if (index < 0 || index >= Size) {throw std::out_of_range("Index out of range");}return data[index];}int getSize() const { return Size; }void print() const {std::cout << "FixedArray[" << Size << "]: ";for (int i = 0; i < Size; ++i) {std::cout << data[i] << " ";}std::cout << std::endl;}
};void nonTypeParamDemo() {std::cout << "\n=== 非类型模板参数 ===" << std::endl;FixedArray<int, 5> intArray;intArray[0] = 10;intArray[1] = 20;intArray.print();FixedArray<double, 3> doubleArray;doubleArray[0] = 1.1;doubleArray[1] = 2.2;doubleArray[2] = 3.3;doubleArray.print();
}

4. 类模板的特化

4.1 完全特化

cpp

#include <cstring>// 主模板
template<typename T>
class Comparator {
public:static bool equal(const T& a, const T& b) {return a == b;}
};// 完全特化 - 针对 const char* 类型
template<>
class Comparator<const char*> {
public:static bool equal(const char* a, const char* b) {return strcmp(a, b) == 0;}
};void specializationDemo() {std::cout << "\n=== 类模板特化 ===" << std::endl;// 使用主模板std::cout << "int equal: " << Comparator<int>::equal(10, 10) << std::endl;std::cout << "string equal: " << Comparator<std::string>::equal("hello", "hello") << std::endl;// 使用特化版本std::cout << "C-string equal: " << Comparator<const char*>::equal("hello", "hello") << std::endl;std::cout << "C-string not equal: " << Comparator<const char*>::equal("hello", "world") << std::endl;
}

4.2 部分特化

cpp

// 主模板
template<typename T1, typename T2>
class MyClass {
public:void show() {std::cout << "Primary template" << std::endl;}
};// 部分特化 - 两个类型相同
template<typename T>
class MyClass<T, T> {
public:void show() {std::cout << "Partial specialization: T, T" << std::endl;}
};// 部分特化 - 第二个类型为 int
template<typename T>
class MyClass<T, int> {
public:void show() {std::cout << "Partial specialization: T, int" << std::endl;}
};// 部分特化 - 两个类型都是指针
template<typename T1, typename T2>
class MyClass<T1*, T2*> {
public:void show() {std::cout << "Partial specialization: T1*, T2*" << std::endl;}
};void partialSpecializationDemo() {std::cout << "\n=== 部分特化 ===" << std::endl;MyClass<int, double> obj1;      // 主模板obj1.show();MyClass<int, int> obj2;         // 部分特化:T, Tobj2.show();MyClass<double, int> obj3;      // 部分特化:T, intobj3.show();MyClass<int*, double*> obj4;    // 部分特化:T1*, T2*obj4.show();
}

5. 实际应用示例

5.1 智能指针模板

cpp

template<typename T>
class SimpleUniquePtr {
private:T* ptr;public:// 构造函数explicit SimpleUniquePtr(T* p = nullptr) : ptr(p) {}// 禁止拷贝SimpleUniquePtr(const SimpleUniquePtr&) = delete;SimpleUniquePtr& operator=(const SimpleUniquePtr&) = delete;// 移动构造SimpleUniquePtr(SimpleUniquePtr&& other) noexcept : ptr(other.ptr) {other.ptr = nullptr;}// 移动赋值SimpleUniquePtr& operator=(SimpleUniquePtr&& other) noexcept {if (this != &other) {delete ptr;ptr = other.ptr;other.ptr = nullptr;}return *this;}// 析构函数~SimpleUniquePtr() {delete ptr;}// 操作符重载T& operator*() const { return *ptr; }T* operator->() const { return ptr; }T* get() const { return ptr; }// 释放所有权T* release() {T* temp = ptr;ptr = nullptr;return temp;}// 重置指针void reset(T* p = nullptr) {delete ptr;ptr = p;}// 布尔转换explicit operator bool() const { return ptr != nullptr; }
};void smartPointerDemo() {std::cout << "\n=== 智能指针模板 ===" << std::endl;SimpleUniquePtr<int> ptr1(new int(42));std::cout << "Value: " << *ptr1 << std::endl;SimpleUniquePtr<std::string> ptr2(new std::string("Hello"));std::cout << "Length: " << ptr2->length() << std::endl;// 移动语义SimpleUniquePtr<int> ptr3 = std::move(ptr1);if (!ptr1) {std::cout << "ptr1 is now empty after move" << std::endl;}std::cout << "ptr3 value: " << *ptr3 << std::endl;
}

5.2 容器模板

cpp

template<typename T>
class DynamicArray {
private:T* data;size_t capacity;size_t size;void resize() {capacity = capacity == 0 ? 1 : 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() : data(nullptr), capacity(0), size(0) {}~DynamicArray() {delete[] data;}void pushBack(const T& value) {if (size >= capacity) {resize();}data[size++] = value;}T& operator[](size_t index) {if (index >= size) {throw std::out_of_range("Index out of range");}return data[index];}const T& operator[](size_t index) const {if (index >= size) {throw std::out_of_range("Index out of range");}return data[index];}size_t getSize() const { return size; }size_t getCapacity() const { return capacity; }void print() const {std::cout << "Array (size=" << size << ", capacity=" << capacity << "): ";for (size_t i = 0; i < size; ++i) {std::cout << data[i] << " ";}std::cout << std::endl;}
};void containerDemo() {std::cout << "\n=== 容器模板 ===" << std::endl;DynamicArray<int> intArray;for (int i = 0; i < 10; ++i) {intArray.pushBack(i * i);}intArray.print();DynamicArray<std::string> strArray;strArray.pushBack("Hello");strArray.pushBack("World");strArray.pushBack("Template");strArray.print();
}

6. 类模板的继承

6.1 模板继承模板

cpp

template<typename T>
class Base {
protected:T value;public:Base(const T& v) : value(v) {}virtual void show() {std::cout << "Base value: " << value << std::endl;}
};template<typename T>
class Derived : public Base<T> {
private:T extraValue;public:Derived(const T& v1, const T& v2) : Base<T>(v1), extraValue(v2) {}void show() override {std::cout << "Base value: " << this->value << ", Extra: " << extraValue << std::endl;}
};void inheritanceDemo() {std::cout << "\n=== 模板继承 ===" << std::endl;Derived<int> derived1(10, 20);derived1.show();Derived<std::string> derived2("Hello", "World");derived2.show();
}

7. 友元和静态成员

7.1 模板中的静态成员

cpp

template<typename T>
class Counter {
private:T value;static int count;  // 静态成员public:Counter(const T& v) : value(v) {count++;}~Counter() {count--;}static int getCount() {return count;}void show() const {std::cout << "Value: " << value << ", Total instances: " << count << std::endl;}
};// 静态成员定义(每个实例化都有自己的一份)
template<typename T>
int Counter<T>::count = 0;void staticMemberDemo() {std::cout << "\n=== 模板静态成员 ===" << std::endl;Counter<int> c1(10);c1.show();Counter<int> c2(20);c2.show();Counter<double> c3(3.14);c3.show();Counter<std::string> c4("Hello");c4.show();std::cout << "Int counters: " << Counter<int>::getCount() << std::endl;std::cout << "Double counters: " << Counter<double>::getCount() << std::endl;std::cout << "String counters: " << Counter<std::string>::getCount() << std::endl;
}

8. 类型推导和 CTAD(C++17)

C++17 类模板参数推导

cpp

template<typename T>
class Point {
private:T x, y;public:Point(T x, T y) : x(x), y(y) {}void show() const {std::cout << "Point(" << x << ", " << y << ")" << std::endl;}
};// 推导指引
template<typename T>
Point(T, T) -> Point<T>;void ctadDemo() {std::cout << "\n=== CTAD (C++17) ===" << std::endl;// C++17 之前需要指定类型Point<int> p1(10, 20);p1.show();// C++17 可以自动推导类型Point p2(3.14, 2.71);  // 推导为 Point<double>p2.show();Point p3("hello", "world");  // 推导为 Point<const char*>p3.show();
}

9. 完整测试程序

cpp

int main() {std::cout << "=== 类模板详解 ===" << std::endl;basicTemplateDemo();           // 基本模板multiParamDemo();              // 多参数模板nonTypeParamDemo();            // 非类型参数specializationDemo();          // 完全特化partialSpecializationDemo();   // 部分特化smartPointerDemo();            // 智能指针containerDemo();               // 容器模板inheritanceDemo();             // 模板继承staticMemberDemo();            // 静态成员ctadDemo();                    // CTADstd::cout << "\n=== 所有演示完成 ===" << std::endl;return 0;
}

10. 总结

类模板的核心概念:

  • 🎯 泛型编程:编写与数据类型无关的代码

  • 🎯 代码复用:同一套逻辑适用于多种类型

  • 🎯 类型安全:编译时类型检查

  • 🎯 性能优化:没有运行时开销

关键特性:

特性说明示例
类型参数template<typename T>支持任意类型
多参数template<T1, T2>多个类型参数
非类型参数template<int Size>值作为参数
特化针对特定类型的优化完全特化、部分特化
继承模板类可以继承代码复用
静态成员每个实例化有自己的静态成员类型特定的计数

最佳实践:

  1. ✅ 使用有意义的模板参数名

  2. ✅ 提供充分的异常安全保证

  3. ✅ 考虑特化以优化特定类型

  4. ✅ 使用概念(C++20)约束模板参数

  5. ✅ 利用 CTAD 简化代码

掌握了类模板,你就掌握了 C++ 泛型编程的核心能力!

http://www.dtcms.com/a/540710.html

相关文章:

  • Selenium IDE下载和安装教程(附安装包)
  • Quartz框架实现根据设置的cron表达式进行定时任务执行
  • linux20 线程同步--信号量
  • 内核的文件预取逻辑及blockdev的相关配置
  • [特殊字符] Web 字体裁剪优化实践:把 42MB 字体包瘦到 1.6MB
  • 平滑过渡,破解多库并存:浙人医基于金仓KFS的医疗信创实战解析
  • 做经营性的网站需要注册什么条件网站构思
  • Answer企业社区实战:零成本搭建技术问答平台,远程协作效率提升300%!
  • “听书”比“看书”更省力?
  • 大连 手机网站案例网站定位方案
  • window安装MYSQL5.5出错:a windows service with the name MYSQL alreadyexists....
  • 珠海做网站报价影响网站排名的因素
  • 6.1.2.2 大数据方法论与实践指南-离线任务SQL 任务开发规范
  • Java 大视界 -- Java 大数据在智能交通高速公路收费系统优化与通行效率提升实战(429)
  • 网站可以做怀孕单吗平面设计图数字标识
  • 图神经网络入门:手写一个 VanillaGNN-从邻接矩阵理解图神经网络的消息传递
  • 网站模版带后台酒类招商网站大全
  • 营销型网站创建网页制作三剑客通常指
  • 【笔试真题】- 电信-2025.10.11
  • 云渲染与传统渲染:核心差异与适用场景分析
  • 什么是流程监控?如何构建跨系统BPM的实时监控体系?
  • 直通滤波....
  • eclipse做网站代码惠州市
  • 零基础新手小白快速了解掌握服务集群与自动化运维(十五)Redis模块-Redis主从复制
  • 视频网站自己怎么做的正规的大宗商品交易平台
  • vue3 实现贪吃蛇手机版01
  • 胶州网站建设dch100室内装修设计师工资一般多少钱
  • 计算机视觉、医学图像处理、深度学习、多模态融合方向分析
  • 小白入门:基于k8s搭建训练集群,实战CIFAR-10图像分类
  • 关系型数据库大王Mysql——DML语句操作示例