简单介绍C++中的模板

目录

一、泛型编程

泛型编程的概念:

泛型编程举例:

二、函数模板

函数模板的概念:

函数模板的格式:

函数模板的实例化:

隐式实例化:

显式实例化:

模板参数的匹配原则:

三、类模板

类模板的格式定义:

类模板的举例:

类模板的实例化:


当我们在编写程序时可能会遇见这样的问题:交换函数是使用频率非常高的函数,当我们想在一个工作台下同时交换char、int、double类型的数据时,我们要怎么做呢?

在C语言中,我们只能通过不同的函数名,对数据类型不同、函数功能相同的函数进行区分。

void Swapi(int left, int right) {//此处省略函数体}
void Swapd(double left, double right) {//此处省略函数体}
void Swapc(char left, char right){//此处省略函数体}
……

由于C++引入了函数重载的概念,使用相同的函数名,编译器可以根据形参的数据类型不同进行区分。

void Swap(int& left, int& right) {//此处省略函数体}
void Swap(double& left, double& right) {//此处省略函数体}
void Swap(char& left, char& right){//此处省略函数体}
……

使用函数重载虽然可以实现,但有几个不好的地方:

  1. 函数从在仅仅时类型不同,代码复用率低,有新类型出现时需要用户自己增加对应函数
  2. 代码可维护性低,当代码出错时,可能需要对所有的代码都需要修改

仔细观察会发现,上述代码只有数据类型不同,其他代码实现都相同。那么是否可以将代码作为模具,将数据类型设为X(未知数据类型),在具体调用时,再将实际的数据类型和X进行替换,就可以实现一份代码,解决函数重载带来的所有问题。因此,引入了泛型编程的思想。

一、泛型编程

泛型编程的概念:

泛型编程是一种编程范式,它的目的是提高代码的重用性和灵活性。泛型编程允许程序员使用不同的数据类型来实现相同的算法和数据结构,从而编写更加通用和可扩展的代码。

泛型编程举例:

实现一个通用的交换函数

//template模板关键字,typename模板中数据类型不是固定的,需要编译器自动推导
template<typename T>
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}int main()
{int a = 10, b = 20;double c = 10.12, d = 20.34;Swap(a, b);Swap(c, d);cout << "a:" << a << "    " << "b:" << b << endl;cout << "c:" << c << "    " << "d:" << d << endl;return 0;
}

二、函数模板

函数模板的概念:

函数模板是一种通用的函数定义形式,允许定义一个接受任意类型参数的函数。它的定义形式类似于一个普通函数,但是使用了类型占位符(通常为T)来代替具体类型。在函数调用时,编译器会根据调用时传递的参数类型来确定T的具体值并生成相应的函数实例。

函数模板的格式:

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表) {}
template<typename T>//typename是用来定义模板参数关键字,也可以使用class
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}

函数模板的实例化:

函数模板并不是实际存在的,只有当系统调用时,才会根据传递过去的实际类型进行实例化。分为隐式实例化和显式实例化

隐式实例化:

编译器根据实参,推演模板参数的实际类型

template<class T>
T Add(const T& left, const T& right) { return left + right; }
int main()
{int a1 = 10, a2 = 20;double d1 = 10.0, d2 = 20.0;Add(a1, a2);//实参是int,编译器将T替换成int,实例化出具体函数Add(d1, d2);//Add(a1, d1);//注意:在模板中,编译器一般不会进行类型转换操作,实参是int和double两种类型,编译器会报错//想解决这种问题有两种方式:1、类型转换;2、显式实例化Add(a1, (int)d1);return 0;
}

显式实例化:

在函数名后,用<>指定模板参数的实际类型

template<class T>
T Add(const T& left, const T& right) { return left + right; }
int main()
{int a = 10;double b = 20.4;// 显式实例化Add<int>(a, b);//如果实参类型和指定的类型不匹配,会进行类型转换,失败会报错return 0;
}

模板参数的匹配原则:

一个非模板参数和一个同名的函数模板同时存在,如果其他条件都相同,首选非模板参数

//非模板函数
int Add(const int& left, const int& right) { return left + right; }//模板函数
template<class T>
T Add(const T& left, const T& right) { return left + right; }int main()
{Add(1, 2);//首选非模板函数Add<int>(1, 2);//显示实例化,会选择模板函数return 0;
}

一个非模板函数和一个同名的函数模板同时存在,函数模板生成的函数更加匹配,会选择函数模板

//非模板函数
int Add(const int& left, const int& right) { return left + right; }//模板函数
template<class T1,class T2>
T1 Add(const T1& left, const T2& right) { return left + right; }int main()
{Add(1, 2);//与非模板函数参数类型相同,首选非模板函数Add(1, 2.0);//与模板函数生成的函数更匹配,选择模板函数return 0;
}

函数模板不能进行隐式类型转换,非模板函数可以进行隐式类型转换

三、类模板

类模板的格式定义:

template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};

类模板的举例:

//模拟vector
//vextor不是一个具体的类,编译器会根据实例化的具体类型从而生成具体类的容器
template<class T>
class vector
{
public:vector(size_t capacity = 10):_pData(new T[capacity]),_size(0),_capacity(capacity){ }//……以下细节省略
private:T* _pData;size_t _size;size_t _capacity;
};

类模板的实例化:

template<class T>
class vector
{
public:vector(size_t capacity = 10):_pData(new T[capacity]),_size(0),_capacity(capacity){ }//……以下细节省略
private:T* _pData;size_t _size;size_t _capacity;
};int main()
{//使用显式实例化指定类型vector<int> v1;return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学会动态规划】最长湍流子数组(23)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…

LeetCode 141.环形链表

文章目录 &#x1f4a1;题目分析&#x1f4a1;解题思路&#x1f514;接口源码&#x1f4a1;深度思考❓思考1❓思考2 题目链接&#x1f449; LeetCode 141.环形链表&#x1f448; &#x1f4a1;题目分析 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中…

怎么系统的学习机器学习、深度学习?当然是看书了

目录 前言 内容简介 学完本书&#xff0c;你将能够 作者简介 本书目录 京东自购链接 前言 近年来&#xff0c;机器学习方法凭借其理解海量数据和自主决策的能力&#xff0c;已在医疗保健、 机器人、生物学、物理学、大众消费和互联网服务等行业得到了广泛的应用。自从Ale…

react实现模拟弹框遮罩的自定义hook

需求描述 点击按钮用于检测鼠标是否命中按钮 代码实现 import React from react; import {useState, useEffect, useRef} from react;// 封装一个hook用来检测当前点击事件是否在某个元素之外 function useClickOutSide(ref,cb) {useEffect(()>{const handleClickOutside…

《论文阅读14》FAST-LIO

一、论文 研究领域&#xff1a;激光雷达惯性测距框架论文&#xff1a;FAST-LIO: A Fast, Robust LiDAR-inertial Odometry Package by Tightly-Coupled Iterated Kalman Filter IEEE Robotics and Automation Letters, 2021 香港大学火星实验室 论文链接论文github 二、论文概…

实践-传统深度学习

简介与安装 2 训练自己的数据集整体流程3 数据加载与预处理4 搭建网络模型5 学习率对结果的影响6 Drop-out操作7 权重初始化方法对比8 初始化标准差对结果的影响9 正则化对结果的影响10 加载模型进行测试 TensorFlow&#xff1a;每一步都需要自己做。 Keras&#xff1a;做起来更…

Electron基础篇

人生有些事,错过一时,就错过一世。 官网&#xff1a;简介 | Electron Electron-大多用来写桌面端软件 Electron介绍 Electront的核心组成是Chromium、Node.js以及内置的Native API&#xff0c;其中Chromium为Electron提供强大的UI能力&#xff0c;可以在不考虑兼容的情况下利…

C# 读取pcd点云文件数据

pcd文件有ascii 和二进制格式&#xff0c;ascii可以直接记事本打开&#xff0c;C#可以一行行读。但二进制格式的打开是乱码&#xff0c;如果尝试程序中读取&#xff0c;对比下看了数据也对不上。 这里可以使用pcl里的函数来读取pcd&#xff0c;无论二进制或ascii都可以正确读取…

【探索Linux】—— 强大的命令行工具 P.5(yum工具、git 命令行提交代码)

阅读导航 前言一、软件包管理器 yum1.yum的概念yum的基本指令使用例子 二、git 命令行提交代码总结温馨提示 前言 前面我们讲了C语言的基础知识&#xff0c;也了解了一些数据结构&#xff0c;并且讲了有关C的一些知识&#xff0c;也学习了一些Linux的基本操作&#xff0c;也了…

php base64转图片保存本地

调用函数 public function base64(){$img $this->request->param(img);$img data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAkACQAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy…

基于springboot的社区生活缴费系统/基于javaweb的水电缴费系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把社区生活缴费管理与现在网络相结合&#xff0c;利用java语言建设社区生活缴费系统&#xff0c;实现社区生活缴费管理的信息化。则对于进一步提高社区生活缴费管理发展&#xff0c;丰富社区生活缴费管理经验能起到不少的促进…

UniApp 制作高德地图插件

1、下载Uni插件项目 在Uni官网下载Uni插件项目&#xff0c;并参考官网插件项目创建插件项目. 开发者须知 | uni小程序SDK 如果下载下来项目运行不了可以参考下面链接进行处理 UniApp原生插件制作_wangdaoyin2010的博客-CSDN博客 2、引入高德SDK 2.1 在高德官网下载对应SD…

Spring Clould 部署 - Docker

视频地址&#xff1a;微服务&#xff08;SpringCloudRabbitMQDockerRedis搜索分布式&#xff09; 初识Docker-什么是Docker&#xff08;P42&#xff0c;P43&#xff09; 微服务虽然具备各种各样的优势&#xff0c;但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中&…

Maven 基础之依赖管理、范围、传递、冲突

文章目录 关于依赖管理坐标和 mvnrepository 网站pom.xml 中"引"包 依赖范围依赖传递依赖冲突 关于依赖管理 坐标和 mvnrepository 网站 在 maven 中通过『坐标』概念来确定一个唯一确定的 jar 包。坐标的组成部分有&#xff1a; 元素说明<groupId>定义当前…

python3 0学习笔记之基本知识

0基础学习笔记之基础知识 &#x1f4da; 基础内容1. 条件语句 if - elif - else2. 错误铺捉try - except(一种保险策略&#xff09;3. 四种开发模式4. 函数&#xff1a;def用来定义函数的5. 最大值最小值函数&#xff0c;max &#xff0c;min6. is 严格的相等&#xff0c;is no…

微服务系列文章之 Springboot+Vue实现登录注册

一、springBoot 创建springBoot项目 分为三个包&#xff0c;分别为controller&#xff0c;service&#xff0c; dao以及resource目录下的xml文件。 UserController.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 …

matlab使用教程(17)—广度优先和深度优先搜索

1.可视化广度优先搜索和深度优先搜索 此示例说明如何定义这样的函数&#xff1a;该函数通过突出显示图的节点和边来显示 bfsearch 和 dfsearch 的可视化结果。 创建并绘制一个有向图。 s [1 2 3 3 3 3 4 5 6 7 8 9 9 9 10]; t [7 6 1 5 6 8 2 4 4 3 7 1 6 8 2]; G dig…

微服务—Eureka注册中心

eureka相当于是一个公司的管理人事HR,各部门之间如果有合作时&#xff0c;由HR进行人员的分配以及调度&#xff0c;具体选哪个人&#xff0c;全凭HR的心情&#xff0c;如果你这个部门存在没有意义&#xff0c;直接把你这个部门撤销&#xff0c;全体人员裁掉&#xff0c;所以不想…

信安通用基础知识

文章目录 密码学经典误区PGP优良保密协议信安经典其它安全手段XSS与CSRF cross site request forgeryCSRF的利用逻辑CSRF示例CSRF防范检查Referer字段添加校验token XSS cross site scripting common weakness enumeration常见密码api误用&#xff08;摘自毕设参考文献&#xf…

蓝蓝设计-ui设计公司-界面设计案例作品

泛亚高科-光伏电站控制系统界面设计 html前端 | 交互设计 | 视觉设计 | 图标设计 泛亚高科(北京)科技有限公司&#xff08;以下简称“泛亚高科”&#xff09;&#xff0c;一个以实时监控、高精度数值计算为基础的科技公司&#xff0c; 自成立以来&#xff0c;组成了以博士、硕…