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

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

目录

1. 非类型模板参数

2. 类模板的特化

2.1 函数模板特化

2.2 类模版特化

3. 模板的分离编译


1. 非类型模板参数

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

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

两者核心区别就是:

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

简单来说就是类型模版参数是改变类型,非类型模版参数改变的是类型后面的数。

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

// 模板参数 <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码。

#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:如果只给一个类的部分参数传递模版参数那就是偏特化。

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

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

Read more

【c++与Linux进阶】线程篇 -互斥锁

【c++与Linux进阶】线程篇 -互斥锁

1. 前言: 在我们之前学习的代码种,就是在建造多线程的路上,我们可以看到出现了乱码或者抢占输出,这是为什么呢? 本章将带着这个问题来带你思考: 1. 一个例子先来领略问题的所在。 2. 什么是线程互斥. 3. 见识互斥锁。 4. 使用互斥锁 2. 一个买票的例子: 假设我们有100张电影票,我们同时抢票会出现什么,我们来尝试写代码来看看: #include<iostream>#include<thread>#include<vector>#include<string>#include<cstdio>#include<unistd.h>int ticket =100;voidroutine(std:

By Ne0inhk
【C++笔记】STL详解:vector容器的使用

【C++笔记】STL详解:vector容器的使用

前言:         本文在介绍STL框架基础上,进一步讲解了迭代器、auto关键字和范围for循环的使用方法,接下来我们将重点探讨vector类的常用接口及其应用。          一、vector容器的简介             C++ 的 vector 是标准模板库(STL)中最核心且实用的容器之一,其与固定大小的传统数组(如 int arr[10])不同,vector 克服了数组的局限性,它不需要预先确定大小,并且可以动态调整容量。          简单理解为:vector是可变的、经过封装函数功能的数组。                  核心优势:          ①动态扩容:您不需要一开始就告诉它要存多少数据。当空间不够时,它会在底层自动帮您寻找一块更大的内存,把数据搬过去。          ②内存安全:它负责自己内存的分配和释放,大大减少了手动 new 和 delete 带来的内存泄漏风险。          ③功能丰富:它自带了大量现成的工具函数,比如:获取大小、清空数据、在尾部添加数据等。

By Ne0inhk

NumCpp实战指南:从零开始掌握C++数值计算的利器

NumCpp实战指南:从零开始掌握C++数值计算的利器 【免费下载链接】NumCppC++ implementation of the Python Numpy library 项目地址: https://gitcode.com/gh_mirrors/nu/NumCpp NumCpp是一个C++实现的Python Numpy库,为C++开发者提供了强大的数值计算能力。无论是科学计算、数据分析还是工程应用,NumCpp都能帮助开发者轻松处理多维数组和矩阵运算,是C++数值计算的必备工具。 为什么选择NumCpp? 熟悉的Numpy风格API NumCpp采用了与Numpy相似的API设计,让熟悉Python Numpy的开发者能够快速上手。这意味着你可以使用类似的函数名称和参数结构,大大降低了学习成本。 高效的C++性能 作为C++库,NumCpp充分利用了C++的性能优势,比纯Python实现的Numpy在计算密集型任务上更快。这使得NumCpp成为处理大规模数据和复杂算法的理想选择。 丰富的功能模块 NumCpp提供了丰富的功能模块,包括线性代数、傅里叶变换、

By Ne0inhk
【C++11】列表初始化、新式声明、范围for和STL中的变化

【C++11】列表初始化、新式声明、范围for和STL中的变化

C++11新特性 * C++11新特性 * github地址 * 0. 前言 * 1. C++与C++11简介 * C++的发展简史 * C++11的意义 * 小故事:C++11命名的由来 * 2. 统一的列表初始化 * C++98中传统的{}初始化 * C++11中统一的列表初始化 * 列表初始化 * std::initializer_list * 引入 * initializer_list介绍 * vector补充支持initializer_list的构造 * map相关 * 3. C++11的新声明 * 1. auto * 1. C++类型系统演进 * 1.1 从C到C++的类型困境 * 1.2 typedef的局限性

By Ne0inhk