【C++精华铺】8.C++模板初阶

news2024/11/17 10:47:35

目录

1. 泛型编程

2. 函数模板

2.1 函数模板的概念及格式

 2.2 函数模板的原理

 2.3 模板的实例化

2.4 模板参数的匹配原则

 3. 类模板

3.1 类模板格式

3.2 类模板的实例化


1. 泛型编程

        什么是泛型编程?泛型编程是避免使用某种具体类型而去使用某种通用类型来进行程序编写的方式,依次来复用某段代码而避免大规模功能相似重复冗余的代码。下面的代码如果想用泛型编程该如何实现。

int add(int a,int b)
{
	return a + b;
}
double add(double a, int b)
{
	return a + b;
}
double add(int a, double b)
{
	return a + b;
}

        马云有次说了这么一句话:“世界是懒人创造的,懒不是傻懒,如果你想少干,就要想出懒的方法。 要懒出风格,懒出境界。”C++必然也是有风格有境界的,所以C++中设计了模板实现了泛型编程。

2. 函数模板

2.1 函数模板的概念及格式

        模板就是一种模具,通过给这个模具中放不同的材料(类型),来获得不同材料的产品,以此来提高我们的工作效率。而函数模板就是某个函数的模具,与类型无关,在使用的时候参数化,在我们给出特定类型就会生成特定类型的版本。

        函数模板的格式:

template<typename T1, typename T2 ...typename Tn>
返回值类型 函数名(形参列表)
{
    //函数体
}

         根据这个函数的模板我们就可以实现上述add函数的模板:

template<typename L, typename R,typename RET>
RET add(L l, R r)
{
	return l + r;
}

注:typename是用来定义模板参数的关键字,也可以用class代替。

 2.2 函数模板的原理

        函数模板本身不是函数,而是一个模具,当我们传入实际类型的时候编译器会根据我们传入的实参类型来推演生成对应类型的函数进行调用。

 2.3 模板的实例化

        当我们将类型传入模板来生产函数的时候,称之为模板的实例化,模板的实例化分为隐式实例化和显式实例化。

        1. 隐式实例化:隐式实例化就是我们不去指定类型,让编译根据我们传入的实参判断其类型传入模板参数列表进行实例化。如下:

template<typename L, typename R>
int add(L l, R r)
{
	return l + r;
}
int main()
{
	int a = 0, b = 1;
	cout << add(a, b) << endl;  //根据我传入的a和b自动判断类型进行模板实例化。
}

        细心的同学发现,这里我将原来的代码中 typename RET 删掉了,原因就是模板不会对函数的返回值类型进行自动判断,而需要我们手动指定(也就是显式实例化)。

        2. 显式实例化:显式实例化就是我们手动向模板传递类型,然后由编译器进行实例化。显式实例化的格式为:

函数名<类型1,类型2,...>(实参列表);

        如: 

template<typename L, typename R, typename RET>
RET add(L l, R r)
{
	return l + r;
}
int main()
{
	int a = 0, b = 1;
	cout << add<int,int,int>(a, b) << endl;
}

        上述代码我们传进去的 a和b的类型与模板参数类型是匹配的,如果不匹配的话编译器会进行隐式类型转化,如果转化失败就报错。如下:
        类型转换成功:

template<typename L, typename R, typename RET>
RET add(L l, R r)
{
	return l + r;
}
int main()
{
	double a = 0.1;
    int b = 1;
	cout << add<int,int,int>(a, b) << endl;  //a:double类型隐式转换成int类型
}

输出:

        类型转化失败: 

template<typename L, typename R, typename RET>
RET add(L l, R r)
{
	return l + r;
}

class Date
{
	//
};
int main()
{
	int a = 0, b = 1;
	cout << add<int,Date,int>(a, b) << endl;  //a:类型转化失败
}

输出:

E0304    没有与参数列表匹配的 函数模板 "add" 实例

2.4 模板参数的匹配原则

        一个函数的模板函数可以与非模板函数同时存在,并且在没有显式实例化且类型匹配的情况下会优先匹配非模板函数,如果是显式实例化才会调用模板,如下。

template<class T>
void swap(T& a, T& b)
{
	std::swap(a, b);
	std::cout << "我是模板 ";
	std::cout << a << ' ' << b << std::endl;

}
void swap(int& a, int& b)
{
	std::swap(a, b);
	std::cout << "我是非模板 ";
	std::cout << a << ' ' << b << std::endl;

}
int main()
{
	int a = 1, b = 2;
	std::cout << a << ' ' << b << std::endl;
	swap(a, b);   //类型匹配优先调用非模板函数
	swap<int>(a, b);  //调用模板实例化
}

输出:

        当我们没有去写模板的时候,函数发生类型不匹配可能会进行隐式类型转换,但是有了模板之后就不会发生隐式类型转化,而是使用模板实例化出来一个更为合适的函数。如下:
        没有模板时会发生隐式实例化:

void test(int a, int b)
{
	std::cout << "我不是模板" << std::endl;
}

int main()
{
	test(2, 2.0);//2.0发生隐式类型转化成int;
}

输出:

        存在模板不会发生隐式类型转化,而是使用模板实例化出来一个更为合适的函数:

template<class T1,class T2>
void test(T1 a, T2 b)
{
	std::cout << "我是模板" << std::endl;
}
void test(int a, int b)
{
	std::cout << "我不是模板" << std::endl;
}
int main()
{
	test(2, 2.0);//不发生隐式类型转化而是隐式实例化模板
}

输出:

 3. 类模板

3.1 类模板格式

        和函数模板一样,类模板是类的一个模具,类模板格式如下:

template<class T1,class T2,class T3,...class Tn>
class 类模板名
{
    //类体
};

        我们普通类是可以声明和定义分离的,如果类模板要实现声明和定义分离,那么在定义的时候也要加上模板声明。如:

template<class T1, class T2>
class A
{
	~A();  //声明
};

template<class T1,class T2> 
A<T1, T2>::~A()   //定义
{
	//...
}

3.2 类模板的实例化

         类模板的实例化和函数模板相同,需要在类名后加上尖括号并且指定类型。注:模板名不是类,实例化后才是一个类。

template<class T>
class Date
{
	//..
};
int main()
{
	Date<int>;
}

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

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

相关文章

FT2000+低温情况下RTC守时问题

1、背景介绍 飞腾2000芯片通过I2C连接一块RTC时钟芯片&#xff08;BellingBL5372&#xff09;来实现麒麟信安系统下后的守时功能。目前BIOS支持UEFI功能&#xff0c;BIOS上电后能获取RTC时间&#xff0c;并将时间写入相应的UEFI变量或内存区域&#xff0c;操作系统上电后使用U…

大模型基础02:GPT家族与提示学习

大模型基础&#xff1a;GPT 家族与提示学习 从 GPT-1 到 GPT-3.5 GPT(Generative Pre-trained Transformer)是 Google 于2018年提出的一种基于 Transformer 的预训练语言模型。它标志着自然语言处理领域从 RNN 时代进入 Transformer 时代。GPT 的发展历史和技术特点如下: GP…

产业园区数字孪生3d可视化全景展示方案

随着数字经济的发展&#xff0c;数字技术给企业发展带来了机遇的同时&#xff0c;也为企业管理带来挑战。比如园区运维&#xff0c;不仅体量大&#xff0c;复杂的运维管理系统&#xff0c;落地难度也较高。那么如何通过数字化手段重塑园区运营&#xff0c;打通园区各业务数据孤…

LimeReport设置当前打印时间

拉一个文本控件&#xff0c;然后填入下面信息&#xff1a; $S{ var curDate new Date(); var strYear curDate.getFullYear().toString(); var strMonth (curDate.getMonth() 1).toString(); var strDay curDate.getDate().toString(); var strHour curDate.getHours().…

句子变形金刚:变相的含义

一、说明 变形金刚完全重建了自然语言处理&#xff08;NLP&#xff09;的格局。在变形金刚出现之前&#xff0c;由于循环神经网络&#xff08;RNN&#xff09;&#xff0c;我们的翻译和语言分类很好——它们的语言理解能力有限&#xff0c;导致许多小错误&#xff0c;而且在大块…

mybatis-x插件的使用

mybatis-x能够帮助我们快速通过数据库生成实体类&#xff0c;mapper层&#xff0c;service层等 下面就带大家如何使用 首先我们去idea里面下载mybatis-x&#xff0c;如下图 我们还需要使用idea连接mysql数据库。效果如下图 接下来我们右键选中表&#xff0c;再选择第一项这个mm…

Panorama SCADA软件在无人值守水泵房的应用

应用背景 城市自来水公司、工矿企业的水泵房普遍数量较多&#xff0c;分布也较分散&#xff0c;在管理上通常会存在需要不定时开关泵、水泵故障不能及时发现、操作人员需24小时轮班值守、人员管理成本高等问题。 虹科Panorama是一个用于构建数据采集、SCADA 和历史解决方案的软…

华为云零代码新手教学-体验通过Astro Zero快速搭建微信小程序

您将会学到 您将学会如何基于Astro零代码能力&#xff0c;DIY开发&#xff0c;完成问卷、投票、信息收集、流程处理等工作&#xff0c;还能够在线筛选、分析数据。实现一站式快速开发个性化应用&#xff0c;体验轻松拖拽开发的乐趣。 您需要什么 环境准备 注册华为云账号、实…

【socket编程简述】TCP UDP 通信总结、TCP连接的三次握手、TCP断开的四次挥手

Socket&#xff1a;Socket被称做 套接字&#xff0c;是网络通信中的一种约定。 Socket编程的应用无处不在&#xff0c;我们平时用的QQ、微信、浏览器等程序.都与Socket编程有关。 三次握手 四次断开 面试可…

Android Selector 的使用

什么是 Selector&#xff1f; Selector 和 Shape 相似&#xff0c;是Drawable资源的一种&#xff0c;可以根据不同的状态&#xff0c;设置不同的图片效果&#xff0c;关键节点 < selector > &#xff0c;例如&#xff1a;我们只需要将Button的 background 属性设置为该dr…

k8s v1.27.4二进制部署记录

记录二进制部署过程 #!/bin/bash#升级内核 update_kernel() {rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.orgyum -y install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpmyum --disablerepo"*" --enablerepo"elrepo-kernel&q…

男装已成越南电商红海赛道,品牌如何突围?

据Metric最新数据&#xff0c;在越南电商市场&#xff0c;男装类目竞争相对激烈&#xff0c;在各大电商平台都已出现饱和迹象。然而&#xff0c;在这片竞争激烈的红海中&#xff0c;仍有品牌找准机会成功突围&#xff0c;为其他品牌提供经验借鉴。 越南男装电商竞争激烈&#…

每天一道leetcode:433. 最小基因变化(图论中等广度优先遍历)

今日份题目&#xff1a; 基因序列可以表示为一条由 8 个字符组成的字符串&#xff0c;其中每个字符都是 A、C、G 和 T 之一。 假设我们需要调查从基因序列 start 变为 end 所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。 例如&#xff0c;&quo…

基于MFCC特征提取和GMM训练的语音信号识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 MFCC特征提取 4.2 Gaussian Mixture Model&#xff08;GMM&#xff09; 4.3. 实现过程 4.4 应用领域 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3…

Kubernetes网络模型

Kubernetes 用来在集群上运行分布式系统。分布式系统的本质使得网络组件在 Kubernetes 中是至关重要也不可或缺的。理解 Kubernetes 的网络模型可以帮助你更好的在 Kubernetes 上运行、监控、诊断你的应用程序。 网络是一个很宽泛的领域&#xff0c;其中有许多成熟的技术。对于…

iPhone(iPad)安装deb文件

最简单的方法就是把deb相关的文件拖入手机对应的目录&#xff0c;一般是DynamicLibraries文件夹 参考&#xff1a;探讨手机越狱和安装deb文件的几种方式研究 1、在 Mac 上安装 dpkg 命令 打包 deb 教程之在 Mac 上安装 dpkg 命令_xcode打包root权限deb_qq_34810996的博客-CS…

shopee物流怎么发货?Shopee新手发货流程解析!

在Shopee平台上开店是许多卖家的第一次尝试&#xff0c;因此他们可能会遇到shopee物流店铺长时间没有订单的情况&#xff0c;但一旦有订单&#xff0c;他们可能又不知道如何发货。下面我介绍shopee物流发货流程&#xff0c;帮助卖家更好地处理订单和发货。 ​首先&#xff0c;让…

easyx图形库基础:5.多物体运动+图片+消息处理

多物体运动图片帧率控制消息处理 一. 多物体运动1.如何合理的管理小球&#xff1a;2.初始化每一个球的信息&#xff1a;3.绘制多物体的运动&#xff1a;4.尝试添加小球个数&#xff1a;num10&#xff1a;![请添加图片描述](https://img-blog.csdnimg.cn/ce058e08c11c4410a7d09d…

线程|线程的使用、四种实现方式

1.线程的实现方式 1.用户级线程 开销小&#xff0c;用户空间就可以创建多个。缺点是&#xff1a;内核无法感知用户级多个线程的存在&#xff0c;把其当作只有一个线程&#xff0c;所以只会提供一个处理器。 2.内核级线程 相对于用户级开销稍微大一点&#xff0c;可以利用多…

【JavaSE】面向对象之继承

继承 继承概念继承的语法父类成员的访问子类和父类没有同名成员变量子类和父类有同名成员变量成员方法名字不同成员方法名字相同 super关键字子类构造方法super和this继承方式 继承概念 继承(inheritance)机制&#xff1a;是面向对象程序设计使代码可以复用的最重要的手段&…