面向对象程序设计之模板进阶(C++)
在之前我出过一篇博客介绍了模版的初阶:面向对象程序设计(C++)模版初阶,接下来我们将进行模版的进阶学习,介绍关于更多模版的知识
1.非类型模版参数
模板参数分类类型形参与非类型形参
类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称
非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用
非类型模版参数相较于宏更加灵活,array中就使用到了非类型模版参数,相当于静态数组,可以根据需要开辟指定大小的数组,array的好处就是可以对于越界检查很有效,并且在栈上开空间,比在堆上更加高效,栈上开空间是向下生长,从高地址到低地址
一般来说普通数组会在数组末尾设置标志位,如果标志位被改变就越界报错,所以一般对于读则不会越界警告,而写入数据会报错
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的
2. 非类型的模板参数必须在编译期就能确认结果
非类型模版
相比与宏更加灵活
只能用于整型,其他类型不可以,char/int/short/bool等整型
C++20支持double类型
template<size_t N>
class Stack
{
private:int _a[N];int _top;
};int main()
{Stack<5> a1;Stack<10> a2;return 0;
}------------------------------------------------------------------------------------------
使用了非类型模版的结构
array:静态数组
对于越界检查很有效
在栈上开空间,比在堆上更加高效
栈上开空间是向下生长,从高地址到低地址int main()
{//一般来说普通数组会在数组末尾设置标志位,如果标志位被改变就越界报错//所以一般对于读则不会越界警告,而写会int a[10] = { 0 };cout << a[11] << endl;a[11] = 1;//静态数组对于越界访问的读与写都会报错array<int, 10> b;cout << b[11] << endl;b[11] = 1;return 0;
}
2.模版的特化
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些 错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该 函数直接给出
函数模板的特化步骤:
1. 必须要先有一个基础的函数模板
2. 关键字template后面接一对空的尖括号<>
3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误
特化
template<class T>
bool LessFun(const T& left, const T& right)
{return left < right;
}特化
这里注意上面的const修饰的是left本身,所以下面特化的const需要在*右边
template<>
bool LessFun<Date*>(Date* const& left, Date* const& right)
{return *left < *right;
}//推荐
bool LessFun(Date* const& left, Date* const& right)
{return *left < *right;
}
2.1全特化
全特化即是将模板参数列表中所有的参数都确定化
类模版特化
1.全特化
template<class T1, class T2>
class Data
{
public:Data() { cout << "Data<T1,T2>" << endl; }
private:T1 _d1;T2 _d2;
};template<>
class Data<int,char>
{
public:Data() { cout << "Data<int,char>" << endl };
}
2.2偏特化
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本
//2.半特化、偏特化
template<class T1>
class Data<T1, double>
{
public:Data() { cout << "Data<T1,double>" << endl };
};//偏特化特殊类型
//传的类型是指针
template<class T1,class T2>
class Data<T1*, T2*>
{
public:Data() { cout << "Data<T1*,T2*>" << endl };
};//传的是引用
template<class T1,class T2>
class Data<T1&, T2&>
{
public:Data() { cout << "Data<T1*,T2*>" << endl };
};
2.2.1部分特化
将模板参数类表中的一部分参数特化
// 将第二个参数特化为inttemplate <class T1> class Data<T1, int>{public:Data() {cout<<"Data<T1, int>" <<endl;}private:T1 _d1;int _d2;
};
2.2.2参数更进一步限制
偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一 个特化版本
//两个参数偏特化为指针类型 template <typename T1, typename T2> class Data <T1*, T2*>
{ public:Data() {cout<<"Data<T1*, T2*>" <<endl;}private:T1 _d1;T2 _d2;
};//两个参数偏特化为引用类型template <typename T1, typename T2>class Data <T1&, T2&>{public:Data(const T1& d1, const T2& d2): _d1(d1), _d2(d2){cout<<"Data<T1&, T2&>" <<endl;}private:const T1 & _d1;const T2 & _d2; };void test2 ()
{Data<double , int> d1; // 调用特化的int版本Data<int , double> d2; // 调用基础的模板 Data<int *, int*> d3; // 调用特化的指针版本Data<int&, int&> d4(1, 2); // 调用特化的指针版本}
3.模版的分离编译
一般地,模版不建议声明与定义分离,如果使用的话有如下解决方法:
1. 将声明和定义放到一个文件 "xxx.hpp" 里面或者xxx.h其实也是可以的。推荐使用这种
2. 模板定义的位置显式实例化。这种方法不实用,不推荐使用

相关文章:
面向对象程序设计之模板进阶(C++)
在之前我出过一篇博客介绍了模版的初阶:面向对象程序设计(C)模版初阶,接下来我们将进行模版的进阶学习,介绍关于更多模版的知识 1.非类型模版参数 模板参数分类类型形参与非类型形参 类型形参即:出现在模板参数列表中,跟在class或…...
电巢科技携Ecosmos元宇宙产品亮相第25届中国光博会
第25届中国国际光电博览会(“CIOE中国光博会”)今日在深圳国际会展中心盛大开幕。本届博览会以“光电引领未来,驱动应用创新”为主题,吸引了全球超过3700家优质光电企业参展,展示了光电产业的最新成果和前沿技术。 电…...
Redis 入门 - 收官
《Redis 入门》系列文章总算完成了,希望这个系列文章可以想入门或刚入门的同学提供帮助,希望能让你形成学习Redis系统性概念。 当时为什么要写这个系列文章,是因为我自己就是迷迷糊糊一路踩坑走过来的,我踩完的坑就踩完了&#x…...
Windows技术栈企业基础底座(1)-为基于Windows的Nginx安装证书
企业的基础环境是一个组织的信息化数字化底座。传统企业基础环境多种系统,应用交杂,多种技术栈使得深入运维成本极大,且人员知识技能较难复用,造成资源浪费。本系列旨在尝试推动这一理念, 建立Windows, 或linux聚焦的技术栈的企业…...
ThreeJS入门(002):学习思维路径
查看本专栏目录 - 本文是第 002篇入门文章 文章目录 如何使用这个思维导图 Three.js 学习思维导图可以帮助你系统地了解 Three.js 的各个组成部分及其关系。下面是一个简化的 Three.js 学习路径思维导图概述,它包含了学习 Three.js 的主要概念和组件。你可以根据这个…...
基于ssm+vue+uniapp的新生报到系统小程序
开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…...
掌握 JavaScript ES6+:现代编程技巧与模块化实践
掌握 JavaScript ES6:现代编程技巧与模块化实践 一 . 变量声明 let二 . 声明常量 const三 . 模板字符串四 . 函数的参数默认值五 . 箭头函数六 . 对象初始化七 . 解构7.1 接收 JSON 对象7.2 接收数组 八 . 延展操作符九 . 导入和导出9.1 方式一9.2 方式二 这篇文章我…...
AttackGen - AI 网络安全事件响应测试工具,附下载链接
为了提高我们团队在安全活动中的响应效率,我关注到了一款叫 AttackGen 的工具,我们需要的是一个既能快速生成场景又能准确反映现实威胁的工具。 在红蓝对抗中,我们经常要模拟各种攻击场景,以测试我们的防御水平。这不仅仅是为了“…...
CAD2020安装方法
文章目录 下载安装包打开压缩包打开文件夹打开CAD2020文件夹双击运行Setup.exe点击安装选择我接受 点击下一步路径默认点击安装等待加载完成安装完成点击立即启动点击OK点击输入序列号点击我同意点击激活输入序列号和 产品钥密点击下一步选择我具有 Autodesk 提供的激活码以管理…...
ubuntu安装mongodb实操学习
一、系统环境 ubuntu 22.04 寻找合适的仓库 经过浏览器里搜索MongoDB Repositories发现这个目录下面有完整的安装包 二、添加到apt,并安装 1、wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | tee /etc/apt/trusted.gpg.d/server-6.0.asc 获取公…...
RabbitMQ 基础入门
文章内容是学习过程中的知识总结,如有纰漏,欢迎指正 文章目录 前言 1. 重要概念 1.1 Publisher 1.2 Message 1.3 Exchange 1.4 BindingKey 1.5 Routingkey 1.6 Queue 1.7 Consumer 1.8 Connection 1.9 Channel 1.10 Virtual Host 1.11Broker 2. RabbitMQ…...
Unity 特殊文件夹
文件夹名称Assets资产Editor编辑器Editor default resources编辑器资源Gizmos辅助图标Plugins插件Resources资源Standard Assets标准资产StreamingAssets流资产PersistentDataPath持久数据 Editor 编辑器文件夹 这个文件夹是专门用来做编辑器级别功能的,比如一些辅…...
Monster Sound FX Pack 2 怪物恶魔野兽声效包
这是受最新电影和游戏启发而创作的一系列超凡怪兽音效中的第二卷。Monster Sound FX Pack 2 包含精心设计的声音,充满个性,为听众带来新的体验。这些声音经过专业设计,是严肃的声音设计师和游戏开发者的必备品! 发现声音非常适合龙、野兽、外星人、兽人、地精、巨人、巨魔、…...
linux常用环境配置
nvm 用于管理不同版本node node版本管理工具 nvm install 18 #安装 nvm uninstall 18 #卸载 nvm use 18 #使用 nvm ls #查看当前有的node版本 nvm ls-remote #列出所有可用的node版本pyenv 在linux中管理多版本 python 常用命令: pyenv install 3.8.…...
SoapShell 更新 | 新增调用cmd执行系统命令
01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失…...
Ubuntu查看系统用户信息
0 Preface/Foreword 1 查看方式 1.1 查看系统用户 getent passwd getent: Get entries for Name Service Switch Libraries. 该命令会列出系统上所有用户的详细信息,包括用户名、密码、用户ID(UID)、组ID(GID)、用户描…...
入门AI绘画 | 手把手教学Stable Diffusion
前言 **Stable Diffusion(简称SD)**就是一个AI自动生成图片的软件,通过我们输入文字,SD就能生成对应的张图片,不再需要像以前一样要把图片“画“出来,或者是“拍“出来 安装非常简单 分为解压整合包和安装…...
基于SpringBoot+Vue+MySQL的热门网络游戏推荐系统
系统展示 用户前台界面 管理员后台界面 系统背景 基于SpringBootVueMySQL的热门网络游戏推荐系统,其背景主要源于当前网络游戏市场的蓬勃发展与用户需求的日益多样化。随着互联网的普及和技术的不断进步,网络游戏已成为人们休闲娱乐的重要方式之一。面对…...
SpringBoot + Vue + ElementUI 实现 el-table 分页功能详解
引言 在现代Web应用程序开发中,前后端分离架构越来越受欢迎。这种架构使得前端和后端开发可以并行进行,提高了开发效率。本文将详细讲解如何使用SpringBoot作为后端,Vue.js和ElementUI作为前端,实现一个带分页功能的数据表格&…...
游戏、网关等服务借助Docker容器化并使用Kubernetes部署、更新等
本文首发在这里 请先看完 实现负责消息转发、推送的网关服务负责网络、定时、坐下、站起、重连等,支持多类游戏的无锁房间 Docker容器化 Build and Push docker build -t panshiqu/game_server:latest -t panshiqu/game_server:1 -t panshiqu/game_server:1.0 -…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
Linux-进程间的通信
1、IPC: Inter Process Communication(进程间通信): 由于每个进程在操作系统中有独立的地址空间,它们不能像线程那样直接访问彼此的内存,所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...
