跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 模板编程入门:函数与类模板详解

C++ 模板是泛型编程的基础,通过函数模板和类模板实现类型无关的代码复用。函数模板的格式、隐式与显示实例化机制,以及类模板的定义特点与内存管理注意事项。内容涵盖从基础语法到实际编码中的常见陷阱,帮助开发者理解编译器如何生成具体类型代码,从而写出更高效的通用组件。

樱花落尽发布于 2026/3/14更新于 2026/10/2498 浏览
C++ 模板编程入门:函数与类模板详解

泛型编程基础

在 C++ 开发中,我们经常遇到需要处理不同类型数据的场景。比如交换两个变量的值,如果分别写 int、double、char 的函数重载,代码量会迅速膨胀且难以维护。

void Swap(int& left, int& right) { 
    int temp = left; left = right; right = temp; 
}
void Swap(double& left, double& right) { 
    double temp = left; left = right; right = temp; 
}
void Swap(char& left, char& right) { 
    char temp = left; left = right; right = temp; 
}

这种重复劳动正是模板存在的意义。就像模具一样,填入不同的类型参数,编译器就能生成具体的代码。泛型编程就是编写与类型无关的通用代码,而模板是它的基石。

一、函数模板

1. 格式与原理

函数模板的基本结构如下:

template<typename T1, typename T2, ..., typename Tn>
返回类型 函数名 (参数列表)
{
    // 函数体
}

注意,typename 是定义模板参数的关键字,这里也可以用 class 替代,但不能用 struct。模板参数的作用域紧跟在 {} 之前。

template<typename T> // 模板参数 -- 类型
void Swap(T& left, T& right) {
    T temp = left;
    left = right;
    right = temp;
}

template<typename T1, typename T2>
T1 Func(const T1& x, const T2& y) {
    cout << x << " " << y << endl;
    return x;
}

在实际调用时,我们不需要关心具体类型,直接传参即可:

int main() {
    int a = 0, b = 1;
    double c = 1.1, d = 2.2;
    Swap(a, b);
    Swap(c, d);
    // Date d1(1949, 10, 1), d2(2015, 7, 3);
    Func(1, 2);
    Func(1, 2.2);
    return 0;
}

底层机制上,调用的是模板实例化出的函数。简单来说,就是把本该由我们手动编写的重复工作交给了编译器去处理。

函数模板实例化示意图

其实 C++ 标准库已经内置了这些功能(如 std::swap),通常不需要自己手写,直接使用即可。

int main() {
    int a = 0, b = 1;
    double c = 1.1, d = 2.2;
    swap(a, b); // 使用标准库
    swap(c, d);
    return 0;
}

2. 函数模板的实例化

模板不会立即生成代码,只有在被调用时才会实例化。主要有两种方式:

  • 隐式实例化:编译器根据实参自动推演模板参数的实际类型。
  • 显示实例化:在函数名后的 < > 中显式指定模板参数的实际类型。
template<typename T>
T Add(const T& left, const T& right) {
    return left + right;
}

template<typename T>
T* Alloc(int n) {
    return new T[n];
}

int main() {
    int a1 = 10, a2 = 20;
    double d1 = 10.1, d2 = 20.2;
    
    cout << Add(a1, a2) << endl;
    cout << Add(d1, d2) << endl;
    
    // 以下报错:编译器无法确定 T 的类型
    // cout << Add(a1, d1) << endl;
    
    // 解决方案 1: 用户强制转换
    // 注意:Add 参数加了 const,因为类型转换会产生临时变量
    cout << Add(a1, (int)d1) << endl;
    cout << Add((double)a1, d1) << endl;
    
    // 解决方案 2: 显示实例化
    cout << Add<int>(a1, d1) << endl;
    cout << Add<double>(a1, d1) << endl;
    
    // 有些函数无法自动推演,只能显示实例化
    double* p1 = Alloc<double>(10);
    return 0;
}

二、类模板

类模板的定义与普通类类似,但类名和类型并不完全一致。例如普通类叫 Stack,而类模板实例化后是 Stack<T>。

template<class T1, class T2, ..., class Tn>
class 类模板名
{
    // 类内成员定义
};

关键点:构造函数不一定能利用模板参数进行推演,因此类模板通常都需要显示实例化。

template<class T>
class Stack {
public:
    Stack(int capacity = 4) {
        _a = new T[capacity];
        _capacity = capacity;
        _size = 0;
    }

    void Push(const T& data) {
        // CheckCapacity();
        _a[_size] = data;
        _size++;
    }

    ~Stack() {
        if (_a) {
            delete[] _a; // 修正:new[] 对应 delete[]
            _a = nullptr;
            _capacity = 0;
            _size = 0;
        }
    }

private:
    T* _a;
    int _capacity;
    int _size;
};

int main() {
    Stack<int> s1;      // 正确
    // Stack<double> s2; // 正确
    // Stack<char> s3;   // 正确
    // Stack<int, double> s4; // 多个模板参数需同时指定
    return 0;
}

关于类模板的声明和定义分离:虽然可以分开写,但最好不要将声明和定义拆分到两个文件中,否则容易引发编译错误(这涉及到模板实例化的时机问题,后续章节会深入讲解)。


模板是 C++ 泛型编程的核心工具,理解其工作原理对于编写高效、通用的组件至关重要。掌握实例化机制和内存管理细节,能让你在实战中避免许多潜在的坑。

目录

  1. 一、函数模板
  2. 1. 格式与原理
  3. 2. 函数模板的实例化
  4. 二、类模板

更多推荐文章

查看全部
  • @anthropic-ai/claude-code 快速上手指南
  • 大模型从零基础入门到精通:核心原理与实战指南
  • 二维差分算法详解:模板题与地毯问题实战
  • 智能家居到智慧城市的数据安全挑战与真实攻击案例
  • Hugging Face 推出四门免费 AI 课程,含中文版本
  • Claude Code 高级编程技巧实战项目详解
  • VSCode 禁用 GitHub Copilot 功能设置指南
  • Python 文档处理实战:python-docx 库详解与应用
  • OpenClaw 结合 cpolar 实现公网访问与应用场景
  • C++ 哈希表原理与模拟实现
  • Spring Cloud 微服务架构概述与工程搭建
  • C/C++ const 关键字详解:变量、指针、函数与类用法
  • C++ 左值引用与右值引用详解
  • Meta-Llama-3-8B-Instruct 部署避坑指南:从环境配置到对话集成
  • 无需修改 hosts 或镜像源加速 Git Clone 及子模块配置
  • Vue3 低代码设计器 EpicDesigner 快速上手指南
  • Android 开发核心知识体系与实战指南
  • OpenAI 发布最强推理模型 o1,性能超越人类专家
  • OpenClaw 部署指南:模型接入与飞书机器人配置
  • 前缀和算法详解与实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online