C++初阶之模板进阶

news2025/3/18 19:26:32

个人主页:点我进入主页

专栏分类:C语言初阶  C语言进阶  数据结构初阶    Linux    C++初阶    算法

欢迎大家点赞,评论,收藏。

一起努力,一起奔赴大厂

目录

一.非类型模板参数

二.模板的特化

2.1引入

2.2全特化

2.3偏特化

三.模板的分离编译

3.1链接错误

3.2链接错误是如何产生的

3.3如何正确分离编译

3.4按需实例化


一.非类型模板参数

        非类型模板参数就是模板的参数有一个常量,我们可以参考下面的代码:

template<class T, size_t N = 10>
class array
{
public :
	T& operator[](size_t index)
	{
		return _arr[index];
	}
	int size()const
	{
		return _size;
	}

private :
	T _arr[N];
	int _size=0;
};

在C++98中我们只支持整形的做为非类型模板参数,在后面的一些版中开始支持其他的类型作为非类型模板参数。在库中我们就有一个类似的设计array这个,我们需要知道这个非常的不好用,因为它实现的功能使用vector就可以实现,而且array在栈上开辟的空间 ,非常容易造成栈溢出,所以可以说这个基本没有任何用处。

二.模板的特化

2.1引入

class Date
{
public:
	friend ostream& operator<<(ostream& _cout, const Date& d);

	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}

	bool operator<(const Date& d)const
	{
		return (_year < d._year) ||
			(_year == d._year && _month < d._month) ||
			(_year == d._year && _month == d._month && _day < d._day);
	}

	bool operator>(const Date& d)const
	{
		return (_year > d._year) ||
			(_year == d._year && _month > d._month) ||
			(_year == d._year && _month == d._month && _day > d._day);
	}
private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day;
	return _cout;
}

template<class T>
bool Less(T left, T right)
{
return left < right;
}
void test1()
{
	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; // 可以比较,结果错误

}

在日期类中我们比较当传入的是值的时候可以比较正确,但是当我i们传入指针时,我们就不能保证这个正确了,这个主要就是比较的是地址,而不是值,因此我们需要特化。

2.2全特化

template<class T>
bool Less(T left, T right)
{
	cout << "Less(T left, T right)" << endl;
	return left < right;
}
template <>
bool Less(Date* left, Date* right)
{
	cout << "Less(Date * left, Date * right)" << endl;
	return *left < *right;
}

        我们需要在已经有的模板上再次写这个模板对它进行特化,但是template后面跟一个尖括号,尖括号里什么也不写,然后将类型写上,再写具体的代码。我们利用上面的代码运行可以看到:

在这里我们比较指针时会走我们的全特化,

2.3偏特化

        偏特化和全特化类似,它只是特化模板的一部分,它就是对参数进一步进行限制,我们可以看下面的代码:

template <class T1,class T2>
class A
{
public :
	A()
	{
		cout<<"A< T1,T2>" << endl;
	}
private:
	T1 _al;
	T2 _a2;
};

template <class T1>
class A<T1,int>
{
public:
	A()
	{
		cout << "A< T1,int>" << endl;
	}
private:
	T1 _al;
	int _a2;
};

template <class T1,class T2>
class A<T1*, T2*>
{
public:
	A()
	{
		cout << "A< T1*, T2*>" << endl;
	}
private:
	T1* _al;
	T2* _a2;
};
void test1()
{
	A<int, char> a1;
	A<int, int>a2;
	A<int*, int*>a3;
}

运行结果为

        在类的使用特化时我们需要在已有的类中再次定义这个类,但是类的后面需要加上括号,括号中的内容是类型,原来的类中的template中有几个参数它就有几个参数,特化的内容不同,没有限制的相同,特化的template中的尖括号为没有精准限制的(它不是一个模糊的,不明确的例如int等,但是参数是T*就需要将T写上)。

三.模板的分离编译

3.1链接错误

        我们将一个类进行分离编译,代码如下:

//.h

namespace bit
{
	template<class T, size_t N = 10>
	class array
	{
	public:
		int size() const;
	private:
		T _array[N];
		int _size=0;
	};
}


//.c

namespace bit
{
	template<class T, size_t N >
	int array<T,N>::size() const 
	{
		return _size;
	}
}

我们实例化一次运行可以看到出现了链接错误

链接错误就是找不到地址,我们可以实验一下,只在.h文件中写一个func函数,调用的时候就会出现链接错误,代码如下:

//.h为
void func();
//.c直接调用

这是由于在编译时有这个声明就可以了,连接时才会进行合并call地址,call的地址就是func定义的地方,但是没有定义,所以出现链接错误。 我们将func函数的定义写好后我们看汇编代码

 它会call一下地址。

3.2链接错误是如何产生的

        在编译阶段开始编译器会把模板进行实例化,由于我们是模板的分离编译,所以我们会造成在.h文件中没有定义的地址,.c文件中有定义但是不知道实例化成什么

3.3如何正确分离编译

        我们需要将声明和定义在同一个.h文件中,这样在编译阶段就会实例化,不需要在链接找地址,我们的代码如下:

	template<class T, size_t N = 10>
	class array
	{
	public:
		int size() const;
	private:
		T _array[N];
		int _size=0;
	};

	template<class T, size_t N >
	int array<T, N>::size() const
	{
		return _size;
	}

3.4按需实例化

我们看代码

	template<class T, size_t N = 10>
	class array
	{
	public:
		int size() const;
		void print()
		{
			cout << size(2);
		}
	private:
		T _array[N];
		int _size=0;
	};

	template<class T, size_t N >
	int array<T, N>::size() const
	{
		return _size;
	}

我们可以看到print函数中是错误的,但是我们不适用print这个函数,编译器就不会报错,一旦使用这个就会出错,我们看两个实验:

bit::array<int> a1;
cout<<a1.size();

	bit::array<int> a1;
	a1.print();

造成这个结果的就是因为编译器会进行按需实例化,当我们需要的时候才会进行实例化,随着版本的更新,编译器在很久以前如果里面少写一个分号也可以编译过去,只要我们不去调用。

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

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

相关文章

盖雅技能发展云,助力制造企业人效合一

制造行业尽管经历多次变革&#xff0c;但企业对人的管理始终是一项高度依赖经验和耗费人力的工作。随着供应链管理和生产设备的自动化、数字化升级&#xff0c;如何将第一生产要素——人&#xff0c;通过数字化的工具融入制造过程的闭环&#xff0c;对企业实现自动化工厂和智能…

【一个糟糕的词:省流】

今日思考&#xff0c;博主分享&#x1f4dd;&#xff0c;原文如下&#xff0c; 我最近听到了一个特别糟糕的词叫省流。我甚至认为这个词可以用来衡量一个人的智商啊&#xff0c;我们可以把一个知识简单的分成三部分问题&#xff0c;答案思维方式就是这个答案是怎么推导出来的啊…

解决Vue项目部署到服务器之后前端向后端发送请求报错404的问题(centos使用docker实现nginx的反向代理)

场景重现&#xff1a; 由于现在流行前后端分离的部署方式&#xff0c;但是按照正确方法部署&#xff08;如何部署可参考&#xff1a;&#xff09;之后&#xff0c;发现明明前后端都部署好了并且运行成功&#xff0c;但是前端发送的请求都是404。明明在vue项目中配置了跨域的相…

信息系统项目管理师十大管理计划内容概览

目录 1.项目章程2.项目管理计划3.范围管理计划4.需求管理计划5.进度管理计划6.成本管理计划7.质量管理计划8.资源管理计划9.沟通管理计划10.风险管理计划11.采购管理计划12.干系人参与计划 点我去AIGIS公众号查看本文 1.项目章程 项目目标成功标准退出标准关键干系人名单发起人…

SpringCloud系列(23)--手写实现负载轮询算法

前言&#xff1a;在上一篇文章中我们介绍了关于负载轮询算法的原理以及看了源代码&#xff0c;而本章节内容则是着重于我们自己手写一个负载轮询算法 1、分别编写provider-payment8001、provider-payment8002这两个子项目的PaymentController类&#xff0c;增加一个/payment/lb…

手把手教你解决 Hive 的数据倾斜

文章目录 数据倾斜是什么&#xff1f;产生数据倾斜的场景1.空值引发的数据倾斜2.不可拆分的大文件产生的数据倾斜3.数值膨胀引发的数据倾斜4.不同数据类型引发的数据倾斜5.Count(distinct) 引发的数据倾斜6.表 Join 操作时引发数据倾斜7.group by 引发的数据倾斜 解决数据倾斜数…

什么是SSL证书?如何选择SSL证书?

在浏览网站的时候&#xff0c;你会不会有这样一些疑问。 为什么有的网站是http://开头&#xff0c;有的却是https://&#xff1f;它们有什么区别吗&#xff1f; 经常访问的网站&#xff0c;浏览器突然提示“安全证书过期”&#xff0c;提醒你不要浏览该网址&#xff1f; 这一切…

推荐一款自助分析的财务分析软件:奥威BI软件

奥威BI软件是一款支持多维度动态自助分析的软件&#xff0c;预设了智能财务分析方案&#xff0c;提供内存行列计算模型解决财务指标计算难题&#xff0c;界面简洁&#xff0c;以点击、拖曳操作为主&#xff0c;十分适合没有IT背景的财务人做财务分析。因此也经常有人说奥威BI软…

前后端开发入门全攻略:零基础学起

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、前后端开发概览 二、后端开发基础&#xff1a;Flask框架入门 代码案例&#xff1a;Hel…

驱动执行报“Attribute var: Invalid permissions 0665”

问题&#xff1a;执行驱动的时候会报下面这个错误 WARNING: CPU: 0 PID: 123 at fs/sysfs/group.c:61 internal_create_group0x170/0x264() Attribute var: Invalid permissions 0665 问题分析&#xff1a;查看 fs/sysfs/group.c:61的代码&#xff0c;发现是我设置 module_par…

Filter和Interceptor

会话 cookie 服务器自动将cookie响应给浏览器 浏览器接收响应回来的数据 自动将cookie存储在本地&#xff0c; 后续请求当中浏览器将cookie携带到服务器 cookie不能跨域&#xff0c;存储在客户端 session 存储在服务器 token------>JWT 存储在客户端&#xff0c; 服务…

独享IP是原生IP吗?二者有何区别?

原生IP&#xff1a; 原生IP是指由Internet服务提供商&#xff08;ISP&#xff09;直接分配给用户的IP地址&#xff0c;这些IP地址通常反映了用户的实际地理位置和网络连接。原生IP是用户在其所在地区或国家使用的真实IP地址&#xff0c;与用户的物理位置直接相关。在跨境电商中…

统计信息和AUTO SQL TUNING任务重合引发的Library Cache Lock血案

一、引言 行里的短信平台&#xff0c;在晚上22:00的时候&#xff0c;突然出现卡顿&#xff0c;卡顿持续1分钟左右&#xff0c;这1分钟内&#xff0c;短信超过30秒才发送成功。因此&#xff0c;对数据库层面开展了一些分析&#xff0c;并且发现了些问题。 二、分析过程 1.查看…

从 0 实现一个文件搜索工具 (Java 项目)

背景 各文件系统下, 都有提供文件查找的功能, 但是一般而言搜索速度很慢 本项目仿照 everything 工具, 实现本地文件的快速搜索 实现功能 选择指定本地目录, 根据输入的信息, 进行搜索, 显示指定目录下的匹配文件信息文件夹包含中文时, 支持汉语拼音搜索 (全拼 / 首字母匹配…

CSS伪类实现input聚焦时,上层div样式改变

CSS伪类实现input聚焦时&#xff0c;上层div样式改变 可以使用:focus-within伪类选择器&#xff0c;它会在div内的任何元素获得焦点时选择该div&#xff0c;明确的是&#xff0c;获得焦点和被点击是不相等的&#xff0c;div能被点击&#xff0c;但是不能获得焦点&#xff0c;也…

ViT:1 从DETR说起

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提供了大模型领域最新技…

东哥一句兄弟,你还当真了?

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 你还真把自己当刘强东兄弟了?谁跟你是兄弟了?你在国外的房子又不给我住&#xff0c;你出去旅游也不带上我!都成人年了&#xff0c;东哥一句客套话&#xff0c;别当真! 今天&#xff0c;东哥在高管会上直言&…

存储+调优:存储-IP-SAN-EXTENSION

存储调优&#xff1a;存储-IP-SAN-EXTENSION 文件系统的锁标记 GFS&#xff08;锁表空间&#xff09; ----------- ------------ ------------- 节点 | ndoe1 | | node2 | | node3 | ---------- ------…

C++成员函数 - 析构函数

析构函数 析构函数 是特殊的成员函数&#xff0c;其 特征 如下&#xff1a; 1. 析构函数名是在类名前加上字符 ~ 。 2. 无参数无返回值类型。 3. 一个类只能有一个析构函数。若未显式定义&#xff0c;系统会自动生成默认的析构函数。注意&#xff1a;析构函数不能重 载 …

K8S认证|CKA题库+答案| 17. 节点维护

17、节点维护 CKA v1.29.0模拟系统免费下载试用&#xff1a; 百度网盘&#xff1a;https://pan.baidu.com/s/1vVR_AK6MVK2Jrz0n0R2GoQ?pwdwbki 题目&#xff1a; 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Ma…