当前位置: 首页 > news >正文

c++模板的简单认识

 

 

文章目录

  • 前言
  • 一.泛型编程
  •      函数模板
  •      模板参数的匹配原则
  •      类模板
  • 总结

 


前言

ADD函数很好写,但是如果我们要有int类型的,double类型的,char类型的等等各种类型,难道要写这么多不同的ADD函数吗,这么写简直太麻烦了,所以有了泛型编程的概念。


 

一、泛型编程

实现一个通用的ADD函数有很多办法,就比如函数重载,但是函数重载又有很多的缺点,比如:

1.重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数。

2.代码的可维护性比较低,一个出错可能所有的重载都出错。

那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生产代码呢?

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

函数模板

函数模板的概念:函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

函数模板格式:

template<typename p1,typename p2........>

注意:typename用来定义模板参数关键字也可以使用class(切记:不能使用struct代替class)
template <class T>
void Swap(T& d1, T& d2)
{T tmp = d1;d1 = d2;d2 = tmp;
}
int main()
{int a = 10, b = 50;Swap(a, b);double c = 2.36, d = 6.15;Swap(c, d);return 0;
}

3b40aac6911a4438bf22fb7ba793e11c.png

那么上图中的两次调用Swap函数是同一个函数吗?这里不是同一个函数,我们先来验证一下:

2a078b1112d14e37b9b44383c42af471.png f3a3c429bf594036a65ca23a55f30a33.png

 通过汇编代码我们发现两个函数并不是同一个,他们有着不同的地址。这是因为模板就像是印刷的模具一样,生成的函数就是印刷出来的书,我们看的是书并不是印刷的板,每本书用的印刷的板都是一样的但是书中的内容是不一样的。

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模 板就是将本来应该我们做的重复的事情交给了编译器。

 e10acf4bb36241c9b20e04ae82d91700.png

 下面我们来看一些关于模板的小细节:

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}
int main()
{int a1 = 10, a2 = 20;double d1 = 10.22, d2 = 20.32;cout << Add(a1, a2) << endl;cout << Add(d1, d2) << endl;return 0;
}

首先上面的代码是可以正常编译的,那么如果写成下面这样呢?

6e2c58f90b304e4fa0c50c06917a0a23.png

这里有两种解决方式,一种是强制类型转换,一种是显式实例化。

int main()
{int a1 = 10, a2 = 20;double d1 = 10.22, d2 = 20.32;//实参传递给形参,自动推演模板类型cout << Add(a1, (int)d1) << endl;cout << Add(d1, d2) << endl;//显示实例化cout << Add<int>(a1, d2) << endl;cout << Add<double>(a1, d1) << endl;return 0;
}

ebf3f3fbd892496faaa16a9d6b77c830.png

 在函数名后加<(需要的类型)>就可以完成显式实例化,编译器直接以显式的类型去计算。

模板参数的匹配原则

// 专门处理int的加法函数
int Add(int left, int right)
{return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{return left + right;
}
void Test()
{Add(1, 2); // 与非模板函数匹配,编译器不需要特化Add<int>(1, 2); // 调用编译器特化的Add版本
}
int main()
{Test();return 0;
}

87d7c08fce4b43aeb6f5d2d9b3e91c6a.png

 我们可以看到上面代码中有两个Add函数,当他们类型都为int的时候为什么没有函数重定义呢?

这是因为一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。

586ed4cd9714418d81e70ccdb1c85a89.png

那么像上图这样的情况编译器会调用哪个呢?答案是第一个,因为对于非模板函数和同名函数模板,如果其他条件都相同,在调用时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的一个函数,那么将选择模板。

什么意思呢?就是说已经存在一个能用的函数了编译器就不会花时间去实例化一个相同的函数,而是调用那个已经存在的函数。

如果我们必须要调用那个模板有什么方法吗?

caced6abeec24b7f9107748a648f8010.png 我们直接在函数名后显示实例化就会调用模板了。

类模板 

template<class T>
class Stack
{
public:Stack(int capacity = 4){_a = new T[capacity];_top = 0;_capacity = capacity;}~Stack(){delete[] _a;_a = nullptr;_top = _capacity = 0;}
paivate:T* _a;size_t _top;size_t _capacity;
};
int main()
{Stack<int> sl;Stack<double> st;return 0;
}

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

注意:模板的声明和定义分开与普通类不一样,如下图:

b832acdbfdc040a6bff91e7d6e533c99.png

9cb58e09c3074b2d85fc4be48a85c823.png 模板的声明和定义分离只限于在一个文件中,如果声明和定义在两个不同的文件会出现链接错误。

0472bfbf0be34f47922594518edffe59.png

模板的类创建对象必须显示实例化在类名后面加<>确定其类型。 

 


总结

模板的出现让我们在写一些代码相同但是类型不同的函数或者类的时候方便了很多,以前这些都是由我们自己写出来的,有了模板就可以由编译器去做这件事,并且编译器做的比我们更好,因为人写总是会出现一些粗心的错误,编译器却不会。

 

相关文章:

c++模板的简单认识

文章目录 前言一.泛型编程 函数模板 模板参数的匹配原则 类模板总结前言 ADD函数很好写&#xff0c;但是如果我们要有int类型的&#xff0c;double类型的&#xff0c;char类型的等等各种类型&#xff0c;难道要写这么多不同的ADD函数吗&#xff0c;这么写简直太麻…...

真香!Linux 原来是这么管理内存的

Linux 内存管理模型非常直接明了&#xff0c;因为 Linux 的这种机制使其具有可移植性并且能够在内存管理单元相差不大的机器下实现 Linux&#xff0c;下面我们就来认识一下 Linux 内存管理是如何实现的。 一&#xff0c;基本概念 每个 Linux 进程都会有地址空间&#xff0c;这…...

计网之IP协议和以太网

文章目录一. IP协议1. IPv4报头介绍2. 解决IPv4地址不够用的问题3. IP地址管理4. 路由选择二. 以太网三. 浅谈DNS域名解析系统一. IP协议 IP协议是位于OSI模型中第三层(网络层)的协议, 在这层上工作的不止这一个协议, 但IP协议是网络层传输所使用的最主流的一种协议, 有IPv4和…...

华为OD机试 - 关联子串(Python) | 机试题+算法思路+考点+代码解析 【2023】

关联子串 题目 给定两个字符串str1和str2 如果字符串str1中的字符,经过排列组合后的字符串中 只要有一个是str2的子串 则认为str1是str2的关联子串 若不是关联子串则返回-1 示例一: 输入: str1="abc",str2="efghicaibii" 输出: -1 预制条件: 输入的…...

SpringBoot学习笔记(二)

配置文件分类 SpringBoot中4级配置文件 1级&#xff1a;file&#xff1a;config/application.yaml 【最高】 2级&#xff1a;file&#xff1a;application.yml 3级&#xff1a;classpath&#xff1a;config/application.yml 4级&#xff1a;classpath&#xff1a;application.…...

亚马逊云科技SageMaker:实现自动、可视化管理迭代

现如今&#xff0c;AI正在成为跨时代的技术&#xff0c;在数字经济发展中登上舞台&#xff0c;发挥关键作用。在Gartner发布的《2022年新兴技术成熟度曲线》*报告中&#xff0c;AIGC&#xff08;即AI Generated Content&#xff0c;人工智能自动生成内容&#xff09;被列为2022…...

汽车 Automotive > CAN Transceivers收发器选择

参考&#xff1a;https://www.nxp.com/products/interfaces/can-transceivers/3-3-v-5-v-io-can-transceivers:33VIO-CAN3.3 V / 5V IO CAN收发器组合TJA1042高速CAN收发器&#xff0c;具有待机模式&#xff0c;适用于所有类型的高速CAN网络&#xff0c;在需要低功耗模式的节点…...

AI将如何影响程序员的未来,以及如何不被AI所替代。

随着人工智能技术的不断发展&#xff0c;越来越多的工作被自动化和智能化所取代&#xff0c;其中程序员这个职业也不例外。然而&#xff0c;我们需要客观地分析AI在未来对程序员的影响&#xff0c;并且给出建议&#xff0c;以便程序员能够保持竞争力&#xff0c;不被AI所取代。…...

nginx 常用配置之 pass_proxy

大家好&#xff0c;我是 17。 今天和大家聊聊 pass_proxy 代理。 pass_proxy 代理 在前端代理主要是为了跨域。虽然前端跨域有多种方法&#xff0c;各有利弊&#xff0c;但用代理来跨域对开发是最友好的。用代理可以不用修改产品代码切换线上线下&#xff0c;非常安全。pass…...

Linux中驱动模块加载方法分析

如何管理驱动模块 由于Linux驱动模块众多&#xff0c;系统对模块加载顺序有要求&#xff0c;一些基础模块在系统启动时需要很早就被加载&#xff1b;开发者加入自己的模块时&#xff0c;需要维护一个模块初始化列表&#xff0c;上面两方面的做起来很困难&#xff0c;为了科学地…...

yarn 通过 resolutions,指定子孙依赖包版本号,解决froala-editor 版本问题

前端开发项目过程中会使用到各种依赖包。但是这些依赖包虽然好用&#xff0c;但是一味使用最新版本可能会出现各种奇葩问题&#xff0c;因此我们经常会针对一些依赖包指定一个稳定版本。 常用版本 版本号注释“1.0.2”必须切到1.0.2版“>1.0.2”必须大于1.0.2版“>1.0.…...

Elasticsearch7.8.0版本进阶——多文档操作流程

目录一、多文档操作1.1、多文档操作的概述1.2、多文档操作与单文档模式区别二、用单个 mget 请求取回多个文档2.1、用单个 mget 请求取回多个文档的图解2.2、用单个 mget 请求取回多个文档的步骤三、bulk API 的模式请求取回多个文档3.1、bulk API 的模式请求取回多个文档的图解…...

Scala函数式编程(第五章:函数基础、函数高级详解)

文章目录第 5 章 函数式编程5.1 函数基础5.1.1 函数基本语法5.1.2 函数和方法的区别5.1.3 函数定义5.1.4 函数参数5.1.5 函数至简原则&#xff08;重点&#xff09;5.2 函数高级5.2.1 高阶函数5.2.2 匿名函数5.2.3 高阶函数案例5.2.4 函数柯里化&闭包5.2.5 递归5.2.6 控制抽…...

ZED相机快速使用指南

1、安装SDK ZED SDK 3.8 - Download | Stereolabs 2、安装ros GitHub - stereolabs/zed-ros-wrapper: ROS wrapper for the ZED SDK 其他教程&#xff1a;ZED2相机SDK安装使用及ROS下使用_可即的博客-CSDN博客 3、官方文档 Get Started with ZED | Stereolabs 4、标定参…...

树莓派4b配置OpenWrt联网

文章目录前言一、下载固件二、配置wan口三、简单介绍1、修改无线名称、设置密码2、下载软件包总结前言 树莓派4b内置wifi模块&#xff0c;加一个千兆网口 好像有一种办法&#xff0c;通过无线wifi链接其他wifi通网&#xff0c;然后把这个网口作为lan口&#xff0c;连接电脑使…...

不同语言下的定时器,你都掌握了吗?

我们大家都对定时器不陌生&#xff0c;无论是现实中还是项目中&#xff0c;都离不开定时。在现实中&#xff0c;它叫闹钟&#xff0c;在项目上&#xff0c;它叫定时器&#xff0c;即定时触发某件事情。它能帮助我们在某一个既定的时间节点上&#xff0c;来提醒我们做一些事情&a…...

华为OD机试 - 水仙花数(Python) | 机试题+算法思路+考点+代码解析 【2023】

水仙花数 题目 所谓的水仙花数是指一个n位的正整数其各位数字的n次方的和等于该数本身, 例如153 = 1^3 + 5^3 + 3^3,153是一个三位数 输入 第一行输入一个整数N, 表示 N 位的正整数 N 在3-7之间包含3,7 第二行输入一个正整数M, 表示需要返回第M个水仙花数 输出描述 返…...

在onBindViewHolder设置View的translation失败或错乱的问题

这个问题&#xff0c;可以换成“为什么在onCreate里面修改一些子View不生效&#xff0c;错位&#xff0c;乱”等问题。 本质原因肯定是在没有把整个ViewGroup渲染完成之前&#xff0c;操作了部分子View&#xff0c;导致了位置偏移等。 解决办法也很简单&#xff0c;通过调用Vi…...

【2.21】MySQL索引、动态规划、学习方法

索引常见面试题 什么是索引 索引的定义就是帮助存储引擎快速获取数据的一种数据结构&#xff0c;形象的说就是索引是数据的目录。存储引擎&#xff0c;说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。索引和数据就是位于存储引擎。…...

华为OD机试题 - 二叉树层次遍历(JavaScript)| 包含代码编写思路

最近更新的博客 华为OD机试题 - 字符串加密(JavaScript) 华为OD机试题 - 字母消消乐(JavaScript) 华为OD机试题 - 字母计数(JavaScript) 华为OD机试题 - 整数分解(JavaScript) 华为OD机试题 - 单词反转(JavaScript) 华为OD机试题 最近更新的博客使用说明二叉树层次遍…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

SQL注入篇-sqlmap的配置和使用

在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap&#xff0c;但是由于很多朋友看不了解命令行格式&#xff0c;所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习&#xff0c;链接&#xff1a;https://wwhc.lanzoue.com/ifJY32ybh6vc…...