17. C++模板(template)1(泛型编程,函数模板,类模板)

⭐本篇重点:泛型编程,函数模板,类模板

⭐本篇代码:c++学习/07.函数模板 · 橘子真甜/c++-learning-of-yzc - 码云 - 开源中国 (gitee.com)

目录

一. 泛型编程

二. 函数模板

2.1 函数模板的格式

2.2 函数模板的简单使用 

 2.3 函数模板的原理

2.4 函数模板的实例化

2.5 模板参数的匹配原则

三. 类模板

3.1 类模板的格式

3.2 类模板的简单使用

3.3 类模板的实例化


一. 泛型编程

        如何实现一个交换函数,这个函数可以交换任意两个相同类型的变量?我们可以使用函数重载来完成这个功能。

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;void swap(int& a, int& b)
{int t = a;a = b;b = t;
}void swap(double& a, double& b)
{double t = a;a = b;b = t;
}void swap(char& a, char& b)
{char t = a;a = b;b = t;
}int main()
{int a = 1, b = 2;double c = 3.14, d = 1.44;char c1 = 'a', c2 = 'b';printf("交换前\na:%d b:%d\nc:%f d:%f\nc1:%c c2:%c\n", a, b, c, d, c1, c2);swap(a, b);swap(c, d);swap(c1, c2);printf("\n\n交换后\na:%d b:%d\nc:%f d:%f\nc1:%c c2:%c\n", a, b, c, d, c1, c2);return 0;
}

运行结果如下:

 

函数重载虽然可以完成这个功能,但是有两个缺点:

1 如果有一个重载的函数出错,可能导致全部函数出问题

2 代码的复用性较低,每增加一个新的类型,都要新增一个重载函数 

        其实,在C++中也存在一种模具,根据填充的材料,获取不同的铸件。就是泛型编程

泛型编程:编写与类型无关的代码,而模板是泛型编程的基础

二. 函数模板

2.1 函数模板的格式

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

注意:typename是用来定义模板参数的关键字,可以使用class替代(不可使用struct替代)

2.2 函数模板的简单使用 

        将swap修改为函数模板后的代码如下:

//使用函数模板
template<class T>
void myswap(T& a, T& b)
{T t = a;a = b;b = t;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;//使用函数模板
template<class T>
void myswap(T& a, T& b)
{T t = a;a = b;b = t;
}int main()
{int a = 1, b = 2;double c = 3.14, d = 1.44;char c1 = 'a', c2 = 'b';printf("交换前\na:%d b:%d\nc:%f d:%f\nc1:%c c2:%c\n", a, b, c, d, c1, c2);myswap(a, b);myswap(c, d);myswap(c1, c2);printf("\n\n交换后\na:%d b:%d\nc:%f d:%f\nc1:%c c2:%c\n", a, b, c, d, c1, c2);return 0;
}

测试结果如下:

 

 2.3 函数模板的原理

        函数模板在编译器编译阶段,编译器根据传入的参数去推导生成对应参数类型的函数用来调用。比如我们传入int型参数,编译器通过推演,将T确定为int型,然后生成一份专门为int型调用的代码。

下图可以帮助我们理解函数模板

2.4 函数模板的实例化

        用不同的参数去使用函数模板的时候,称为函数模板的实例化。函数模板的实例化有显示实例化和隐式实例化。

隐式实例化:让编译器根据实参去自动推演参数类型

显示实例化: 在调用函数时候,在函数名后面加上<>,在<>中指定参数的类型       

 上面的交换函数swao就是隐士实例化的例子

显示实例化:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;//使用函数模板
template<class T>
T add(const T& a, const T& b)
{return a + b;
}int main()
{int a = 1, b = 2;double c = 3.14, d = 1.44;cout << "a + b = " << add<int>(a, b) << endl;cout << "c + d = " << add<double>(c, d) << endl;int ret = add<int>(a, c); //如果参数类型和指定类型不一样,编译器会转化cout << "ret:" << ret << endl;return 0;
}

 如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

2.5 模板参数的匹配原则

        一个非模板函数可以和一个同名模板函数同时存在,并且这个模板函数可以被实例化为这个非模板函数

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;//非模板函数
int add(const int& a, const int& b)
{return a + b;
}//使用函数模板
template<class T>
T add(const T& a, const T& b)
{return a + b;
}int main()
{int a = 1, b = 2;double c = 3.14, d = 1.44;int ret1 = add(a, b);		//调用非模板函数int ret2 = add<int>(a, b);	//调用显示实例化的add函数double ret3 = add(c, d);	//调用double类型的add函数cout << ret1 << endl << ret2 << endl << ret3;return 0;
}

运行结果如下:

        对于非模板函数和同名模板函数 ,在调用条件相同的情况下,编译器会优先去调用非模板函数。如果模板函数可以产生一个更匹配的函数,则会调用模板函数

        模板函数不允许自动类型转化,普通函数支持自动类型转化

三. 类模板

        与函数模板一样,我们也可以使用类模板。

3.1 类模板的格式

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

3.2 类模板的简单使用

这里使用一个模板数组(支持传入的类型)来举例:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;template<class T>
class arr
{
public:arr():_a(nullptr), _size(0), _capacity(0){};~arr(){//销毁开辟的空间delete[] _a;_size = 0;_capacity = 0;}//插入函数void PushBack(const T& x){if (_size == _capacity){size_t newcapacity = (_capacity == 0) ? 3 : _capacity * 2;T* tmp = new T[newcapacity];if (_a != nullptr){memcpy(tmp, _a, sizeof(T) * _size);delete[] _a;    //注意要销毁旧的空间,防止内存泄漏!_a = nullptr;}_a = tmp;_capacity = newcapacity;}_a[_size] = x;_size++;}void print(){for (int i = 0; i < _size; i++){cout << _a[i] << " ";}cout << endl;}
private:T* _a;size_t _size;size_t _capacity;
};int main()
{//定义一个int类型的数组arr<int> nums;for (int i = 0; i < 10; i++){nums.PushBack(i);}nums.print();//定义一个char类型的数组arr<char> str;for (int i = 0; i < 10; i++){str.PushBack('a' + i);}str.print();return 0;
}

运行结果如下:

3.3 类模板的实例化

        类模板的实例化与函数模板的实例化不同,类模板的实例化需要在模板名后面加上<>,并且在<>指明这个类型。

        就像上面的代码:arr是模板名字,arr<int>和arr<char>才是类名字

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

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

相关文章

Jupyter Notebook的安装和配置提示功能

Python开发环境搭建conda管理环境-CSDN博客 安装anaconda和对接到编译器的教程可以看上面这一篇 Jupyter Notebook是一种交互式计算环境&#xff0c;它允许用户在单个文档中编写和执行代码、方程、可视化和文本。与其他编译器相比&#xff0c;Jupyter Notebook的突出点在于其交…

maxun爬虫工具docker搭建

思路来源开源无代码网络数据提取平台Maxun 先把代码克隆到本地&#xff08;只有第一次需要&#xff09; git clone https://github.com/getmaxun/maxun.git 转到maxun目录 cd maxun 启动容器 docker-compose --env-file .env up -d 成功启动六个容器 网址 http://local…

剑指Offer26.树的子结构

题目让判断B是不是A的子结构 但是我们进行判断是基于 两个树的根相等时, 去判断是否为子结构 针是否等于B的根节点的值对A做先序遍历的过程中 如果根节点相同我们去判断此时B是不是以该根节点的子树的子结构! 实际上进行先序遍历的同时要进行递归判断子结构 B是不是A节点的子结…

2024御网杯信息安全大赛个人赛wp(misc方向)

目录 一.信息安全大赛的通知二、编码转换1. 第一部分2. 第二部分3. 第三部分 三、1.txt四、buletooth 题目附件以及工具链接&#xff1a; 通过网盘分享的文件&#xff1a;御网杯附件 链接: https://pan.baidu.com/s/1LNA6Xz6eZodSV0Io9jGSZg 提取码: jay1 –来自百度网盘超级会…

【云计算网络安全】解析 Amazon 安全服务:构建纵深防御设计最佳实践

文章目录 一、前言二、什么是“纵深安全防御”&#xff1f;三、为什么有必要采用纵深安全防御策略&#xff1f;四、以亚马逊云科技为案例了解纵深安全防御策略设计4.1 原始设计缺少安全策略4.2 外界围栏构建安全边界4.3 访问层安全设计4.4 实例层安全设计4.5 数据层安全设计4.6…

实战OpenCV之物体跟踪

基础入门 物体跟踪技术是一种计算机视觉领域的重要技术&#xff0c;用于连续地检测和定位视频序列中的一个或多个目标物体。物体跟踪技术在众多领域都有广泛的应用&#xff0c;比如&#xff1a;自动驾驶、安防监控、增强现实等。物体跟踪的基本流程包含以下几个主要步骤。 1、初…

Linux环境变量(添加环境变量、修改系统环境变量、内建命令和非内建命令)

Linux环境变量&#xff08;添加环境变量、修改系统环境变量、内建命令和非内建命令&#xff09; 1. 环境变量的介绍 环境变量&#xff08;environment variables&#xff09;一般是指在操作系统中用来指定操作系统运行环境的一些参数。环境变量是在操作系统中一个具有特定名字…

排序算法之插入排序篇

插入排序 思路&#xff1a; 就是将没有排序的元素逐步地插入到已经排好序的元素后面&#xff0c;保持元素的有序 视频的实现过程如下&#xff1a; 插入排序全过程 代码实现过程如下&#xff1a; public static void Insertion(int[] arr) { for (int i 1; i < arr.length…

AVL、B树和B+树

AVL树定义 AVL树&#xff08;Adelson-Velsky 和 Landis 树&#xff09;是一种自平衡的二叉搜索树&#xff08;Binary Search Tree, BST&#xff09;&#xff0c;由苏联数学家Georgy Adelson-Velsky和Evgenii Landis在1962年提出。AVL树通过在每个节点上维护一个平衡因子&#…

Unity ShaderLab 实现3D物体描边

实现思路&#xff1a; 给物体添加第二个材质球&#xff0c;在shader的顶点着色器中使顶点的位置变大&#xff0c;然后在片元着色器中输出描边颜色。 shader Graph实现如下&#xff1a; ShaderLab实现如下&#xff1a; Shader "Custom/Outline" {Properties{[HDR]_…

【C++第三方库】Muduo库结合ProtoBuf库搭建服务端和客户端的过程和源码

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 本章我将结合之前的这俩个第三方库快速上手protobuf序列化和反序列化框架和muduo网络&#xff0c;来去实现muduo库在protocol协议搭建服务端和客户端。…

Jenkins的使用

文章目录 一、Jenkins是什么\有什么用\与GitLab的对比二、Jenkins的安装与配置Jenkins的安装方式在Linux上安装Jenkins&#xff1a;在Windows上安装Jenkins&#xff1a;配置Jenkins&#xff1a; &#xff08;可选&#xff09;配置启动用户为root&#xff08;一定要是root吗??…

Qml-TabBar类使用

Qml-TabBar类使用 TabBar的概述 TabBar继承于Container 由TabButton进行填充&#xff0c;可以与提供currentIndex属性的任何容器或布局控件一起使用&#xff0c;如StackLayout 或 SwipeView&#xff1b;contentHeight : real:TabBar的内容高度&#xff0c;用于计算标签栏的隐…

Cyberchef 辅助网络安全运营-数据格式转换

在网络安全的世界中&#xff0c;经常会遇到各种格式的数据&#xff0c;比如二进制&#xff0c;比如说16进制&#xff0c;URL编码&#xff0c;HTML编码&#xff0c;Unicode编码&#xff0c;Base格式的编码。网络安全运营一个明确的目标就是把这些不同的数据格式换成为可读的字符…

C语言——指针初阶(一)

目录 一.什么是指针&#xff1f;&#xff1f;&#xff1f; 指针是什么&#xff1f; 指针变量&#xff1a; 总结&#xff1a; 总结&#xff1a; 二.指针和指针类型 指针-整数&#xff1a; 总结&#xff1a; 指针的解引用 总结&#xff1a; 三.野指针 如何规避野指针 往期…

Tcon技术和Tconless技术介绍

文章目录 TCON技术&#xff08;传统时序控制器&#xff09;定义&#xff1a;主要功能&#xff1a;优点&#xff1a;缺点&#xff1a; TCONless技术&#xff08;无独立时序控制器&#xff09;定义&#xff1a;工作原理&#xff1a;优点&#xff1a;缺点&#xff1a; TCON与TCONl…

World of Warcraft /script SetRaidTarget(“target“, n, ““) n=8,7,6,5,4,3,2,1,0

魔兽世界执行当前目标标记方法 /script SetRaidTarget("target", n, "") n8,7,6,5,4,3,2,1,0 解析这个lua脚本 D:\Battle.net\World of Warcraft\_classic_\Interface\AddOns\wMarker wMarker.lua /script SetRaidTarget("target", 8, &quo…

学习笔记035——MySQL索引

数据库索引 索引是为了提高数据的查询速度&#xff0c;相当于给数据进行编号&#xff0c;在查找数据的时候就可以通过编号快速找到对应的数据。 索引内部数据结构&#xff1a;B Tree 主键自带索引。 如&#xff1a; insert into user (id, name) values (1,f); insert int…

在Unity中实现物体动画的完整流程

在Unity中&#xff0c;动画是游戏开发中不可或缺的一部分。无论是2D还是3D游戏&#xff0c;动画都能为游戏增添生动的视觉效果。本文将详细介绍如何在Unity中为物体添加动画&#xff0c;包括资源的准备、播放组件的添加、动画控制器的创建以及动画片段的制作与调度。 1. 准备动…

Python数据分析实例五、US 大选捐款数据分析

美国联邦选举委员会 (FEC) 公布了对政治竞选活动的贡献数据。这包括投稿人姓名、职业和雇主、地址和投款金额。2012 年美国总统大选的贡献数据以单个 150 MB 的 CSV 文件P00000001-ALL.csv形式提供,该文件可以通过以下pandas.read_csv加载: import pandas as pdfec = pd.r…