C++之模版详解(进阶)

目录

[1. 非类型模板参数](#1. 非类型模板参数)

[2. 类模板的特化](#2. 类模板的特化)

[2.1 函数模板特化](#2.1 函数模板特化)

[2.2 类模版特化](#2.2 类模版特化)

[3. 模板的分离编译](#3. 模板的分离编译)


**1.**非类型模板参数

模版参数有两种,一种叫类型模版参数,一种叫做非类型模版参数。今天我们来讲讲非类型模版参数。

template <int N> 中的 int N 就是典型的非类型模板参数。这里的 int 是参数的类型,而 N 是参数名,它接收的是一个具体的常量值 ,而非像普通类型模板参数(如 template <typename T>)那样接收一个 "类型"。

两者核心区别就是:

  • 类型模板参数:传递 "类型"(如 T = int
  • 非类型模板参数:传递 "常量值"(如 N = 10

简单来说就是类型模版参数是改变类型,非类型模版参数改变的是类型后面的数。
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
2. 非类型的模板参数必须在编译期就能确认结果。

cpp 复制代码
// 模板参数 <int N> 就是非类型参数(传递的是"值")
template <int N>  // N 是一个编译期已知的整数
class FixedArray {
private:
    int arr[N];  // 用 N 作为数组长度(编译时就确定了)
public:
    // 打印数组长度
    void printSize() {
        std::cout << "数组长度是:" << N << std::endl;
    }
};

int main() {
    // 实例化时指定具体的"值"(非类型参数)
    FixedArray<3> arr3;  // N=3,创建一个长度为3的数组
    FixedArray<5> arr5;  // N=5,创建一个长度为5的数组

    arr3.printSize();  // 输出:数组长度是:3
    arr5.printSize();  // 输出:数组长度是:5

    return 0;
}

**2.**类模板的特化

2.1 函数模板特化

模板的特化(Template Specialization)是 C++ 中为模板提供 "特殊处理" 的机制。简单说就是:当模板的参数满足某种特定条件时,我们可以为它定义一套专门的实现,而不使用通用模板的代码

比如说下面这个代码,第一个Print就是普通的模版,第二个Print就是特化的模版。我们要在函数的名字后面加上<char>说明我们要特殊处理的是char类型的。由于计算机是从上往下编译的,所以当它在mian函数里面遇到Print,同时里面是char类型的时候,它会自动匹配第二个,然后打印出对应的ASCII码。

cpp 复制代码
#include <iostream>

// 通用模板(适用于大多数类型)
template <typename T>
void Print(T value) {
    std::cout << "通用模板:" << value << std::endl;
}

// 对 char 类型的特化版本
template <>  // 特化标记:空参数列表,表示"针对特定类型"
void Print<char>(char value) {  // 明确指定特化的类型:char
    std::cout << "char 特化:字符 '" << value << "' 的 ASCII 码是 " << (int)value << std::endl;
}

int main() {
    Print(123);    // 匹配通用模板,输出:通用模板:123
    Print('A');    // 匹配 char 特化版本,输出:char 特化:字符 'A' 的 ASCII 码是 65
    return 0;
}

2.2 类模版特化

下面这个就是类模版特化中的全特化,简单来说就是给类的每一个参数都传递模版参数,就叫做全特化。

PS:如果只给一个类的部分参数传递模版参数那就是偏特化。

cpp 复制代码
#include <iostream>
#include <string>

// 通用类模板:处理任意类型的数据
template <typename T>
class DataProcessor {
public:
    void process(T data) {
        std::cout << "通用处理:" << data << "(类型未知,按默认方式处理)" << std::endl;
    }
};

// 全特化:专门处理 int 类型
template <>  // 全特化标记(空参数列表)
class DataProcessor<int> {  // 明确指定特化的类型是 int
public:
    void process(int data) {
        std::cout << "int 专用处理:" << data << "(整数翻倍后为 " << data * 2 << ")" << std::endl;
    }
};

// 全特化:专门处理 string 类型
template <>
class DataProcessor<std::string> {  // 明确指定特化的类型是 string
public:
    void process(std::string data) {
        std::cout << "string 专用处理:" << data << "(字符串长度为 " << data.size() << ")" << std::endl;
    }
};

int main() {
    // 测试通用模板(处理 double 类型,没有特化版本)
    DataProcessor<double> dProc;
    dProc.process(3.14);  // 用通用模板处理

    // 测试 int 特化版本
    DataProcessor<int> iProc;
    iProc.process(10);    // 用 int 专用处理

    // 测试 string 特化版本
    DataProcessor<std::string> sProc;
    sProc.process("hello");  // 用 string 专用处理

    return 0;
}

**3.**模板的分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链 接起来形成单一的可执行文件的过程称为分离编译模式,比如说我写的那个boost搜索引擎项目就是分离编译模式。

这个就相当于写了一个通用的类,然后我们想用时对他进行调用。

相关推荐
D_evil__3 小时前
【Effective Modern C++】第三章 转向现代C++:16. 让const成员函数线程安全
c++
微风中的麦穗3 小时前
【MATLAB】MATLAB R2025a 详细下载安装图文指南:下一代科学计算与工程仿真平台
开发语言·matlab·开发工具·工程仿真·matlab r2025a·matlab r2025·科学计算与工程仿真
2601_949146534 小时前
C语言语音通知API示例代码:基于标准C的语音接口开发与底层调用实践
c语言·开发语言
开源技术4 小时前
Python Pillow 优化,打开和保存速度最快提高14倍
开发语言·python·pillow
学嵌入式的小杨同学4 小时前
从零打造 Linux 终端 MP3 播放器!用 C 语言实现音乐自由
linux·c语言·开发语言·前端·vscode·ci/cd·vim
Queenie_Charlie5 小时前
前缀和的前缀和
数据结构·c++·树状数组
mftang5 小时前
Python 字符串拼接成字节详解
开发语言·python
jasligea6 小时前
构建个人智能助手
开发语言·python·自然语言处理
kokunka6 小时前
【源码+注释】纯C++小游戏开发之射击小球游戏
开发语言·c++·游戏
Guheyunyi6 小时前
智能守护:视频安全监测系统的演进与未来
大数据·人工智能·科技·安全·信息可视化