C++: 模板(进阶)

news2024/11/26 15:41:28

学习目标

1.了解非类型模板参数

2.了解类模板的特化

3.知道模板分离编译会出现的问题

1.非类型模板参数(整型常量)

模板参数:

1.类型形参:在模板参数列表中,class/typename后的参数名称

2.非类型形参:整型常量

示例:

	template<class T ,size_t N>
	class arr
	{
	public:
		//......
	private:
		T _arr[N];//根据传递过来的N,来决定开多大的数组
		size_t _size;
	};

	void test1()
	{
		arr<int, 10> arr1;
	}

2.模板的特化

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板

// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
	return left < right;
}
int main()
{
	cout << Less(1, 2) << endl; // 可以比较,结果正确
	Date d1(2022, 7, 7);
	Date d2(2022, 7, 8);
	cout << Less(d1, d2) << endl; // 可以比较,结果正确
	Date* p1 = &d1;
	Date* p2 = &d2;
	cout << Less(p1, p2) << endl; // 可以比较,结果错误(比较的是指针)
	return 0;
}

此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化类模板特化

函数模板特化

1. 必须要先有一个基础的函数模板
2. 关键字template后面接一对空的尖括号<>
3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误

// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
	return left < right;
}

// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{
	return *left < *right;
}

一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出。

bool Less(Date* left, Date* right)
{
	return *left < *right;
}

类模板的特化

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; }
private:
	int _d1;
	char _d2;
};

2.偏特化

基础的类模板:

template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

偏特化:任何针对模版参数进一步进行条件限制设计的特化版本

偏特化有两种表中形式:1.部分特化2.参数更进一步的限制

1.部分特化:

// 将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:
	Data() { cout << "Data<T1, int>" << endl; }
private:
	T1 _d1;
	int _d2;
};

2.参数更进一步的限制

//两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

3.模板的分离编译

1.什么是分离编译

分离编译模式:一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程

2.模板的分离编译

2.1模板声明和定义分离为什么会导致链接错误?

我们先将模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义

//tfunc.h
template<class T>
T Add(const T& left, const T& right);

//func.cpp
template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}

//test.cpp
int main() 
{
	Add(1,2);
	Add(1.0,2.0);
	return 0;
}

效果:

这里看到链接错误了

但普通的函数时可以声明和定义分离的:

这是因为普通函数在编译的时候会被编译成指令

模板声明和定义分离后,不知道实例化出什么类型,没有被编译成指令

于是在链接的时候,找不到模板实例化出的函数Add的地址,因此报错

进程中有一个寄存器,用来记录当前执行到那一句指令,每一句指令都有一个地址

通过寄存器可以知道这段代码执行到了哪里,当这段程序执行时间到后,被切换出去,保存这个寄存器,等后面切换回来的时候,根据这个寄存器,来继续执行后面的代码

2.2为什么声明和定义放在一起后就不会链接错误了?

预处理的过程会将头文件展开,若声明定义放在一起,在test.cpp文件中展开后,调用该函数的时候,就会知道T的类型,知道这个函数的地址,会生成相关的指令

声明和定义放在一起后直接就可以实例化在编译的时候就有地址,不需要再连接

3.解决方法

1.显示实例化:

//func.h
template<class T>
T Add(const T& left, const T& right);

template
double Add<double>(const double& left, const double& right);

template
int Add<int>(const int& left, const int& right);

2.声明和定义放在一起

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1042631.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker和Docker compose的安装使用指南

一&#xff0c;环境准备 Docker运行需要依赖jdk&#xff0c;所以需要先安装一下jdk yum install -y java-1.8.0-openjdk.x86_64 二&#xff0c;Docker安装和验证 1&#xff0c;安装依赖工具 yum install -y yum-utils 2&#xff0c;设置远程仓库 yum-config-manager --add-r…

什么是AI问答机器人?它的应用场景有哪些?

近年来&#xff0c;由于技术的进步和对个性化客户体验的需求不断增长&#xff0c;AI问答机器人也是获得了巨大的关注。AI问答机器人&#xff0c;也被称为AI聊天机器人&#xff0c;是一种旨在模拟人类对话并通过基于文本或语音的界面与用户交互的计算机程序。其能够自动执行各种…

idea Springboot在线商城系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 在线商城系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有 完整的源代码和数据库&…

SpringCloud篇

SpringCloud五大组件是啥&#xff1f; rabbin gateway feign 注册中心&#xff08;nacos,Eureka&#xff09;,服务保护 &#xff08;sentinel&#xff09; &#xff1b; nacos和eureka的区别是什么&#xff1f; 负载均衡是如何实现的&#xff1f;&#xff1f; ribbon负载策略…

kaggle新赛:Optiver 美股价格预测赛题解析

赛题名称&#xff1a;Optiver - Trading at the Close 赛题链接&#xff1a;https://www.kaggle.com/competitions/optiver-trading-at-the-close 赛题背景 证券交易所是快节奏、高风险的环境&#xff0c;每一秒都很重要。随着交易日接近尾声&#xff0c;强度不断升级&#…

常见逻辑漏洞总结

Web安全测试中常见逻辑漏洞解析&#xff08;实战篇&#xff09; 简要&#xff1a; 越权漏洞是比较常见的漏洞类型&#xff0c;越权漏洞可以理解为&#xff0c;一个正常的用户A通常只能够对自己的一些信息进行增删改查&#xff0c;但是由于程序员的一时疏忽&#xff0c;对信息…

2024年浙江理工大学MBA项目报考形势如何?

浙江理工大学MBA项目怎么样&#xff0c;值不值得报考&#xff1f;2024年的最新招生政策已经出来&#xff0c;浙江理工大学MBA项目有全日制和非全日制两个MBA方向招生&#xff0c;分别招收19人和52人&#xff0c;总体招生规模不大&#xff0c;这也是浙江理工大学MBA项目近些年的…

锐思WMS和金蝶云星辰V1单据接口对接

锐思WMS和金蝶云星辰V1单据接口对接 来源系统:金蝶云星辰V1 金蝶云星辰基于金蝶云苍穹云原生PaaS平台构建&#xff0c;聚焦小型企业在线经营和数字化管理&#xff0c;提供财务云、税务云、进销存云、零售云、订货商城等SaaS服务&#xff0c;支持企业拓客开源、智能管理、实时决…

批量删除wordpress文章修订版本/自动草稿残留数据(3种方法)及四种方法禁用WordPress文章历史修订/自动保存/自动草稿功能

目录 1、批量删除wordpress文章修订版本/自动草稿残留数据&#xff08;3种方法&#xff09; 方法一&#xff1a;SQL命令批量删除 命令&#xff1a; 方法二&#xff1a;利用PHP代码来删除 方法三&#xff1a;利用数据库清理优化插件 WP Clean Up 或 WP Cleaner 批量删除 2…

VEX —— Functions|Math

目录 sign —— 返回给定数的符号标签 abs —— 返回绝对值 avg —— 返回平均值 sum —— 求和 max —— 返回最大值 min —— 返回最小值 rint —— 返回四舍五入后的整数 ceil —— 返回最近的最大整数 floor —— 返回最近的最小整数 frac —— 返回浮点值的小数…

8个值得收藏的免费激光点云数据集

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 在 3D 城市点云分析领域&#xff0c;存在多种方法&#xff0c;包括半自动和自动方法。 尽管该领域显示出巨大的潜力&#xff0c;但尚未就最佳检测、分割和分类方法达成共识。 为了鼓励创新&#xff0c;我们收集了 8个免费的…

怎样设置每个月的10号提醒?可每月触发提醒的软件是哪个

在每个月当中总是会有一些需要按时提醒的事情&#xff0c;如每月10号提醒换房贷、每月10号提醒还信用卡、每月10号提醒续交车贷等&#xff0c;当然每月像这样的事情是比较多的&#xff0c;怎样设置每个月的10号提醒自己呢&#xff1f; 可以用来设定定时提醒的工具是比较多的&a…

vue3黑马笔记

一、创建vue3项目 需要node16版本或者以上&#xff0c; npm init vuelatest二、vue3模块 在vue3中所有的创建都用了函数封装&#xff0c;保证了每个实例的独立性 三、setup 1、setup选项 setup组合式api 1、执行时间比beforeCreate还早 2、setup函数&#xff0c;获取不到this…

M1/M2芯片Parallels Desktop 19安装使用教程(超详细)

引言 在Window上VMware最强&#xff0c;在Mac上毫无疑问Parallels Desktop为最强&#xff01; 今天带来的是最新版Parallels Desktop 19的安装使用教程。 1. 下载安装包 Parallels Desktop 19安装包&#xff1a;https://www.aliyundrive.com/s/ThB8Fs6D3AD Parallels Deskto…

ctfshow web入门(21-28爆破)

web21 抓包 进行了base64加密&#xff0c;解码后发现账号和密码格式是 账号:密码 爆破 位置一开始选错了&#xff0c;应该是不含Basic的 模式选择custom iterator(自定义迭代器) 自定义迭代器可以自定义拼接方式 分别设置三个位置&#xff0c;第一个位置为admin 第二个位置…

HONEYWELL 0574-A-012 0574-A-0131 工控DCS系统模块

工业控制分布式控制系统&#xff08;DCS&#xff09;模块是用于自动化和监控工业过程的关键组件。它们具有多种功能和特点&#xff0c;以满足工业自动化的不同需求。以下是工控DCS系统模块的一些常见产品特点&#xff1a; 分布式控制&#xff1a;HONEYWELL 0574-A-012 0574-A-0…

外汇天眼:多平台涉嫌欺诈,各监管机构出手打击!

在当今快速发展的金融领域&#xff0c;随着外汇和加密货币市场的崛起&#xff0c;投资者们享受到了前所未有的多元化投资机会。然而&#xff0c;这个多元化的市场也引来了一些不法分子&#xff0c;威胁着投资者的资金和信任。就在上周&#xff0c;多个平台涉嫌欺诈&#xff0c;…

VBA学习方法3.2.4:VBA中的查找操作

【分享成果&#xff0c;随喜正能量】一旦被欲望的毒箭射中&#xff0c;心会变得麻木&#xff0c;失去觉知&#xff0c;甚至疯狂。如果没有及时清醒&#xff0c;就会如同爱美的飞蛾扑向火焰、贪吃的鱼儿被鱼钩钓起&#xff0c;当发现自己身处险境时&#xff0c;后悔也来不及了。…

nodeJs+jwt实现小程序tonken鉴权

nodeJsjwt实现小程序tonken鉴权 自我记录 config\config.js // 配置文件 module.exports {DBHOST: 127.0.0.1,DBPORT: 27017,DBNAME: test,secret: xxxxx,// 小程序的appSecretAppID: xxxxx,// 小程序的appId }token中间件 middlewares\checkTokenMiddleware.js //导入 jwt…

密码学【第一节:密码学概述】

前言 在区块链的整个体系中大量使用了密码学算法&#xff0c;比如用于 PoW 的哈希算法&#xff0c;用于完整性验证的 Merkle Tree&#xff0c;用于交易签名与验证的数字签名算法&#xff0c;用于隐私保护的零知识证明等等。 可以说密码学是保证区块链安全的基石&#xff0c;而区…