C++——模板的作用2:特例化

      目录

模板的形式:

一.模板的多参数应用:

例:

错误使用1:使用不标准的模板形参表

​编辑 

错误使用2:使用变量作为实参传递给函数模板

二.模板的特例化:

类模板:

针对模板的特化步骤:

类模板的全特化:

类模板的半特化:

半特化的扩展: 

三. 模板总结


          在之前,我介绍过一篇关于C++模板的作用,它的出现解决了C语言对多种不同类型的但是有着相同作用函数的难题,举个例子:想要作用于两个整型变量的交换,那么使用C语言可以写出整型交换的函数,但是又出现了char型、double型、short型变量的交换,那么就需要再写出这三个类型的交换函数,而这几个函数写出来后唯一的不同点就是返回值和形参的不同,造成了代码的冗余,可读性变差

模板的形式:

template <模板形参表>

返回值类型 函数体(模板函数形参表)

{

}

        而模板的出现使得交换函数只需要写一个就够,极大的缩减了代码,增加了函数的复用性,为泛型编程打下了坚实的基础!

(478条消息) C++基础——模板讲解_橙予清的zzz~的博客-CSDN博客https://blog.csdn.net/weixin_69283129/article/details/127845086

感兴趣的朋友门可以来看看这篇文章,它会加深你对模板的理解。 

而接下来我要讲的是模板的另外几个作用:

一.模板的多参数应用:

非类型模板参数 模板参数分类类型形参与非类型形参。

        1.类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。

        2.非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

在上面的那篇博客中,我所列举的模板例子中用到的全都是类型形参。 

 // 定义一个模板类型的静态数组
 template<class T, size_t N = 10>
 class array{
     public:
         T& operator[](size_t index){
            return _array[index];
            }
         const T& operator[](size_t index)const{
            return _array[index];
            }
 
         size_t size()const{
            return _size;
            }
         bool empty()const{
            return 0 == _size;
            }
 
     private:
         T _array[N];
         size_t _size;
         };

         通过上图代码可知:模板形参列表中出现了非类型形参。该参数可以是变量,但其类型只能是整型,这个整型包括:char、int、size_t等类型!而使用自定义类型、浮点类型的变量是不被允许的!会报编译错误!

例:

运行结果: 

错误使用1:使用不标准的模板形参表

错误使用2:使用变量作为实参传递给函数模板


二.模板的特例化:

类模板:

函数模板是对函数进行泛型的使用,让函数能够对多种类型的变量做相应的操作;

而类模板就算对类进行泛型的使用,让类中的成员变量或者函数做相应的复杂操作。

//类模板样例1:
template<class T1,class T2>
class Date {
public:
	Date() {
		cout << "模板:Date(T1,T2)" << endl;
	}
private:
	T1 _a1;
	T2 _b1;

};

针对模板的特化步骤:

1. 必须要先有一个基础的函数模板或者类模板

2. 关键字template后面接一对空的尖括号<>

3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型

4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。 

类模板的全特化:

        全特化即是将模板参数列表中所有的参数都确定化。

//类模板的特殊化处理——全部参数特殊化处理
template<>
class Date<double,double>{
public:
	Date() {
		cout << "全特化:Date(double, double)" << endl;
	}
private:
	double _a1;
	double _b1;
};

//类模板的特殊化处理——全部参数特殊化处理2
template<>
class Date<short,char> {
public:
	Date() {
		cout << "全特化:Date(short, char)" << endl;
	}
private:
	short _a1;
	char _b1;
};

        如上,全特化的类模板所使用的模板形参列表相比较普通的类模板,类型是全部确定的。全特化的作用就是:在一般的情况下,普通的对象被创建时使用普通类模板即可,做着普通的工作。而在某种特殊情况下,我们可以让对象被创建时使用专门的经过特殊化处理的类模板,做一些特殊的操作。 

类模板的半特化:

        针对模版参数进一步进行条件限制设计的特化,即部分特化模板参数列表。

//半参数特殊化处理——案例1:
template<class T2>
class Date<double, T2> {
public:
	Date() {
		cout << "半特化:Date(double, T2)" << endl;
	}
private:
	double _a1;
	T2 _b1;
};

//半参数特殊化处理——案例2:
template<class T1>
class Date<T1, char> {
public:
	Date() {
		cout << " 半特化:Date(T1, char)" << endl;
	}
private:
	T1 _a1;
	char _b1;
};

        类模板原本是T1,T2两个类型的参数,使用半特化就是将T1具体化成double类型作为模板参数。 

int main(){
    Date<int, int> d1;
	Date<double, double>d2;	
	Date<short,char>d3;	
	Date<double, int> d4;	
	Date<int, char> d5;		
    return 0;
    }

接着,我们在main函数中使用类创建几个对象,看编译器会进入哪些类模板中!

运行结果: 

代码解析:

        通过结果可知:d1的创建是调用了类模板T1,T2的构造函数,d2,d3是调用了全特化的类模板构造函数,d4,d5调用了半特化的类模板构造函数。

        将这些比作生活的例子:当时间到了吃中午饭的时候,编译器饿了,在它面前有三种吃法:1.自己拿食材做(炒,炸,烧,爆,煎,煮);2.做省时省力的半成品饭;3.点外卖。而T1,T2类型的类模板好比是从超市买回来的新鲜食材,需要编译器自己去做才能吃;半特化的类模板好比是半成品,例如:方便面、自热饭、昨晚的剩饭剩菜,需要编译器进行小小的加工就可以吃了;而全特化的类模板好比是外卖,是现成的热乎的香喷喷的饭菜。在不考虑金钱和健不健康的情况下,我们的做法肯定是选择好吃美味而且省时省力的外卖,编译器的思想也和我们一样——有现成的就不会自己动手再去做。

        所以编译器在对d1对象的调用时,发现没有完美符合<int,int>的类模板,那么只能去自己做(使用T1,T2模板的构造函数);

        而对于d2对象的调用,发现double,double的构造函数选项有两种,一种是选择<T1,T2>的类,另一种是选择<double,double>的类,那编译器肯定是选择后者。

         ......

半特化的扩展: 

        半特化还可以应用于指针、引用的类型上!

template<class T1,class T2>
class Date<T1*,T2*> {
public:
	Date() {
		cout << "半特化:Date(T1*,T2*)" << endl;
	}
private:
	T1* _a1;
	T2* _b1;
};

//半特化4——两个参数偏特化为引用类型
template<class T1, class T2>
class Date<T1&, T2&> {
public:
	Date(const T1& d1, const T2& d2)
		: _d1(d1)
		, _d2(d2)
	{
		cout << "半特化:Data<T1&, T2&>" << endl;
	}

private:
	const T1 & _d1;
	const T2 & _d2;
};


三. 模板总结

优点:

1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生

 2. 增强了代码的灵活性 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot的static静态资源访问、参数配置、代码自定义访问规则

目录 1. 静态资源1.1 默认静态资源1.2 Controller高优先级1.3 修改静态资源的URL根路径1.4 修改静态资源的目录1.5 访问webjars依赖包的静态资源1.6 静态资源的关闭1.7 静态资源在浏览器的缓存1.8 静态资源实战1.9 通过代码自定义静态资源访问规则 1. 静态资源 查看源码如下&a…

【前端工程化】未使用docker时,前端项目实现线上秒级回滚

目录 一. 前言 二. 思路 三. 实践 3.1 准备单页应用项目 3.2 保存历史构建index.html内容 3.3 模拟服务端托管前端应用 3.4 快速回滚node服务端代码开发 3.5 快速回滚前端可视化页面开发 3.6 快速回滚测试 四. 总结 一. 前言 项目快速回滚是前端工程化中很重要的一环&…

【LeetCode每日一题】——566.重塑矩阵

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 矩阵 二【题目难度】 简单 三【题目编号】 566.重塑矩阵 四【题目描述】 在 MATLAB 中&…

HTML5中的data-*属性

介绍&#xff1a; data-*全局属性是一类被称为自定义数据属性的属性&#xff0c;它赋予我们在所有 HTML 元素上嵌入自定义数据属性的能力。 data-*的使用 <div class"child" data-name"小红" data-age"18"></div> 在js里有两种获…

Vue2 第二节 ----初识Vue(简单示例,模板语法,数据绑定)

知识点&#xff1a; 1.Vue的简单示例 2.模板语法 3.数据绑定 4.el和data的两种写法 5.MVVM模型 一. Vue的简单实例 <div id"root"><h1>hello, {{name.toUpperCase()}}, {{address}}</h1></div><script type"text/javascript&q…

ChatGPT 是如何工作的:从预训练到 RLHF

欢迎来到人工智能的未来&#xff1a;生成式人工智能&#xff01;您是否想知道机器如何学习理解人类语言并做出相应的反应&#xff1f;让我们来看看ChatGPT ——OpenAI 开发的革命性语言模型。凭借其突破性的 GPT-3.5 架构&#xff0c;ChatGPT 席卷了世界&#xff0c;改变了我们…

[Java] 单例设计模式详解

模式定义&#xff1a;保证一个类只有一个实例&#xff0c;并且提供一个全局访问点&#xff0c;时一种创建型模式 使用场景&#xff1a;重量级的对象&#xff0c;不需要多个实例&#xff0c;如线程池&#xff0c;数据库连接池 单例设计模式的实现 1.懒汉模式&#xff1a;延迟…

066、故障处理之热点问题

为什么要解决热点 分布式架构中各个组件的理想状态&#xff1a;资源利用率相对均衡 形成写热点的原因 高频访问的小表SQL执行计划不合理具有顺序增长属性的索引扫描 数据组织模型 例如数据是序列递增&#xff0c;则有可能数据全部都集中一个region上 &#xff0c;或者集中…

6、用restful风格写controller方法接口,单元测试依赖

编写单元测试&#xff0c;用restful风格写controller方法 单元测试依赖 实际项目开发中&#xff0c;单元测试与业务代码通常都会要求同步进行 TDD测试驱动开发&#xff1a;先编写单元测试&#xff0c;然后努力去开发业务代码去满足所有的单元测试用例。 添加SpringBoot的测试…

Springer独立出版 | 2023年触觉与虚拟现实国际会议(ICHVR 2023)

会议简介 Brief Introduction 2023年触觉与虚拟现实国际会议(ICHVR 2023) 会议时间&#xff1a;2023年12月15日-17日 召开地点&#xff1a;中国北海 大会官网&#xff1a;www.ichvr.org 2023年触觉与虚拟现实国际会议(ICHVR 2023)由东南大学、上海交通大学联合主办&#xff1b;…

Python-ElasticSearch客户端的封装(聚合查询、统计查询、全量数据)

目录 ES Python客户端介绍封装代码测试代码参考 ES Python客户端介绍 官方提供了两个客户端elasticsearch、elasticsearch-dsl pip install elasticsearchpip install elasticsearch-dsl第二个是对第一个的封装&#xff0c;类似ORM操作数据库&#xff0c;可以.filter、.group…

com.android.ide.common.signing.KeytoolException:

签名没问题但是提示Execution failed for task :app:packageDebug. > A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable > com.android.ide.common.signing.KeytoolException: Failed to read ke…

github gitlab 多用户多平台切换

一、背景 我需要用账号1 来登录并管理github 账号 我需要用账号2 来登录并管理gitlab 账号 二、设置账号 邮箱 设置账号1用户名与邮箱 git config --global user.name "miaojiang" git config --global user.email "187133163.com" 三、生成本地密钥…

pycharm配置arcpy环境

目录 1、安装ArcGIS软件2、安装PyCharm3、创建PyCharm项目4、验证ArcPy环境 在GIS开发中&#xff0c; ArcPy是不可或缺的重要组件&#xff0c;而PyCharm作为一款功能强大的Python IDE&#xff0c;为我们提供了更便捷、高效的开发环境。在本文中&#xff0c;我们将详细介绍如何…

sublime配置less的一些坑(1)

仅在sublime的Install Package安装保存less报错 在sublime的Install Package安装less 打开sublime软件,按住CtrlShiftP组合键,弹出的界面中选择Install Package 选中后enter或者回车。等会弹出一个弹窗,大致意思是说你已经成功安装了package control。如果你在此之前已经安装了…

【力扣每日一题】2023.7.31 重排链表

目录 题目&#xff1a; 示例: 分析: 代码: 题目&#xff1a; 示例: 分析: 给我们一个链表&#xff0c;让我们按照题目要求原地修改重排链表。 那么具体怎么个重排法呢&#xff0c;题目给出了一串式子&#xff0c;其实就是把链表分为前后两段&#xff0c;然后在前半段的节…

企业工程管理系统源码之提高工程项目管理软件的效率

高效的工程项目管理软件不仅能够提高效率还应可以帮你节省成本提升利润 在工程行业中&#xff0c;管理不畅以及不良的项目执行&#xff0c;往往会导致项目延期、成本上升、回款拖后&#xff0c;最终导致项目整体盈利下降。企企管理云业财一体化的项目管理系统&#xff0c;确保…

UML/SysML建模工具更新(2023.7)(1-5)有国产工具

DDD领域驱动设计批评文集 欢迎加入“软件方法建模师”群 《软件方法》各章合集 最近一段时间更新的工具有&#xff1a; 工具最新版本&#xff1a;Visual Paradigm 17.1 更新时间&#xff1a;2023年7月11日 工具简介 很用心的建模工具。支持编写用例规约。支持文本分析和C…

小目标检测(1)——大恒(DaHeng)相机操作与控制编程

文章目录 引言正文相关开发库的介绍编程准备配置引用头文件GalaxyIncludes.h配置lib文件 具体编程过程初始化和反初始化枚举设备开关设备 属性控制属性控制器种类 图像采集控制和图像处理采单帧回调采集图像处理流对象属性控制 获取设备事件获取掉线事件通知 样例程序分析补充&…

重生之我要学C++第五天

这篇文章主要内容是构造函数的初始化列表以及运算符重载在顺序表中的简单应用&#xff0c;运算符重载实现自定义类型的流插入流提取。希望对大家有所帮助&#xff0c;点赞收藏评论&#xff0c;支持一下吧&#xff01; 目录 构造函数进阶理解 1.内置类型成员在参数列表中的定义 …