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

类模板的语法

1. 什么是类模板

  • 类模板(class template)是 “类型的模板”——它将一个或多个类型参数非类型参数抽象出来,让一个“通用的类框架”能在编译期被实例化成针对不同类型或不同值的具体类。

  • 作用:通用代码复用静态多态在容器/工具类实现中最常见


2. 基本语法

// 声明一个带 1 个类型参数 T 的类模板
template <typename T>        
class MyClass {
public:// 成员变量T value;// 构造函数MyClass(const T& v) : value(v) {}// 成员函数void print() const {std::cout << value << std::endl;}
};
  • template <typename T>:告诉编译器,接下来定义的是一个类模板,T 是一个占位类型

  • MyClass<T>:当你写 MyClass<int> 时,编译器会 生成一个名为 MyClass 的实际类


3. 如何使用(实例化)

int main() {// 1) 指定类型参数MyClass<int>  mi(42);mi.print();             // 输出 42MyClass<std::string> ms("Hello");ms.print();             // 输出 Hello// 2) C++17 结构化绑定 + CTAD(类模板参数推导)MyClass m2(3.14);       // 自动推断 T 为 doublem2.print();             // 输出 3.14
}
  • 显式实例化MyClass<int>MyClass<std::string> 都是针对不同类型生成的“真实类”。

  • CTAD(Class Template Argument Deduction):C++17 起,如果构造函数参数能唯一推断模板参数,就可以省略 <...>


4. 多模板参数与非类型模板参数

4.1 多类型参数

template <typename Key, typename Value>
class Pair {
public:Key   first;Value second;Pair(const Key& k, const Value& v) : first(k), second(v) {}
};

使用:

Pair<std::string,int>  p("age", 30);
std::cout << p.first << ": " << p.second << std::endl;

4.2 非类型模板参数

// size 是一个整型常量(编译期已知)
template <typename T, int size>
class FixedArray {T data[size];
public:T& operator[](int i) { return data[i]; }int getSize() const { return size; }
};

使用:

FixedArray<double, 5> arr;
for(int i = 0; i < arr.getSize(); ++i)arr[i] = i * 1.1;

5. 模板的实现分离

  • 头文件.hpp.h 中同时放声明定义,或者

  • .h:声明 + #include "MyClass.tpp"
    .tpp:模板定义(实现)
    因为模板必须在使用点可见实现,才能实例化。

// MyClass.hpp
#pragma once
template<typename T>
class MyClass {T v;
public:MyClass(const T&);void print() const;
};
#include "MyClass.tpp"// MyClass.tpp
#include <iostream>
template<typename T>
MyClass<T>::MyClass(const T& _v) : v(_v) {}
template<typename T>
void MyClass<T>::print() const {std::cout << v << std::endl;
}

6. 模板特化

6.1 完全特化(full specialization)

对某个具体类型做专门实现:

// 通用版本
template<typename T>
struct TypeName { static std::string name() { return "Unknown"; } };// 针对 int 完全特化
template<>
struct TypeName<int> { static std::string name() { return "int"; } };// 用法
std::cout << TypeName<double>::name(); // Unknown
std::cout << TypeName<int>::name();    // int

6.2 偏特化(partial specialization)

对一组类型做专门实现(只针对模板类,函数模板不支持偏特化):

// 针对指针类型的偏特化
template<typename T>
struct TypeName<T*> {static std::string name() { return TypeName<T>::name() + "*"; }
};// 用法
std::cout << TypeName<int*>::name();   // int*

7. 模板模板参数(更高级)

允许把“模板本身”作为参数:

template< template<typename> class Container, typename T >
class Wrapper {Container<T> c;
public:void add(const T& v) { c.insert(c.end(), v); }
};// 使用 vector 作为 Container 模板
Wrapper<std::vector, int> w;
w.add(10);

8. 小结与注意事项

  1. 模板是在编译期展开:每种参数组合都会生成独立代码,可能导致可执行文件变大。

  2. 定义与声明要都可见:否则编译器无法实例化。

  3. 特化:完全特化和偏特化用法不同,偏特化只适用于类模板。

  4. CTAD:C++17 支持类模板参数推导,调用时可省略模板参数列表。

  5. 避免虚函数+模板:模板类加虚函数会多一层复杂度,按需使用。

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

相关文章:

  • 计算机网络实验——网线的制作和测试
  • 网安-SSRF-pikachu
  • RNN及其变体的概念和案例
  • Vue响应式原理一:认识响应式逻辑
  • python 为什么推荐使用虚拟环境(如 venv)?它解决了什么问题?
  • doris2.1.8连接报错ERROR 1203 (42000): Reach limit of connections解决办法
  • 使用 Docker Compose 简化 INFINI Console 与 Easysearch 环境搭建
  • Oracle:使用ONLINE选项创建索引
  • 【内核基础精讲】I2C 子系统核心概念与结构全解析
  • 类与对象【下篇】-- 关于类的其它语法
  • 蓝凌EKP产品:属性转换器系统优化
  • c语言学习_函数递归2
  • 70、【OS】【Nuttx】【构建】配置 stm32 工程
  • STM32继电器万能控制设备
  • 【04】MFC入门到精通——MFC 自己手动新添加对话框模板 并 创建对话框类
  • SpringBoot集成文件 - 大文件的上传(异步,分片,断点续传和秒传)
  • 数据结构基础准备:包装类 泛型 泛型的上界 密封类
  • 零知开源——STM32F407VET6驱动SHT41温湿度传感器完整教程
  • 2023年全国青少年信息素养大赛Python编程小学组复赛真题+答案解析-北京赛区
  • idea 常用快捷键
  • Mysql中的日志-undo/redo/binlog详解
  • 学习open62541 --- [79] 在docker中运行open62541工程
  • pytorch chunk 切块
  • 【C++】容器适配器 + stack/queue/deque详解
  • Java基础,反射破坏封装性 - 单例模式的崩塌
  • 掌握PDF转CAD技巧,提升工程设计效率
  • 第四节 chatPDF
  • 机器视觉之工业相机讲解
  • unity animtor播放动画的指定位置
  • spring boot使用mybatis-plus实现分页功能