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搜索引擎项目就是分离编译模式。

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

相关推荐
Georgeviewer5 小时前
商业落地评测|实体门店GEO优化性价比与服务体系深度复盘
大数据·人工智能
Scott9999HH6 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔6 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
GIR1236 小时前
官方出品 | 多通道土壤呼吸测量系统市场现状与十五五规划深度报告:行业分析+趋势预测全收录
大数据·人工智能·机器学习
2401_841495647 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
fqbqrr7 小时前
2607C++,soui与安卓
c++·soui
码智社7 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海7 小时前
python 列表、元组、集合和字典
开发语言·python
南讯股份Nascent8 小时前
洽洽全域会员项目启动会圆满召开
大数据·人工智能
大郭鹏宇8 小时前
基于 LangGraph 构建智能分诊系统(一):项目概述与环境搭建
大数据·人工智能·microsoft·langchain