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.rhkb.cn/news/479624.html

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

相关文章

学习threejs,设置envMap环境贴图创建反光效果

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.CubeTextureLoader 立…

v-for产生 You may have an infinite update loop in a component render function

参考文章&#xff1a; 报错解析 [Vue warn]: You may have an infinite update loop in a component render function. 另外一个解决方法 例如: MyList 是一个数组&#xff0c;我希望将排序后的结果返回进行for循环&#xff0c;因此设计了一个myMethon函数 <div v-for"…

spring boot框架漏洞复现

spring - java开源框架有五种 Spring MVC、SpringBoot、SpringFramework、SpringSecurity、SpringCloud spring boot版本 版本1: 直接就在根下 / 版本2:根下的必须目录 /actuator/ 端口:9093 spring boot搭建 1:直接下载源码打包 2:运行编译好的jar包:actuator-testb…

【Linux】线程的互斥和同步

【Linux】线程的互斥和同步 线程间的互斥 临界资源&#xff1a;多线程执行共享的资源就叫做临界资源临界区&#xff1a;每个线程内部&#xff0c;访问临界资源的代码&#xff0c;就叫做临界区互斥&#xff1a;任何时刻&#xff0c;互斥保证有且只有一个执行流进入临界区&#…

集合Queue、Deque、LinkedList、ArrayDeque、PriorityQueue详解

1、 Queue与Deque的区别 在研究java集合源码的时候&#xff0c;发现了一个很少用但是很有趣的点&#xff1a;Queue以及Deque&#xff1b; 平常在写leetcode经常用LinkedList向上转型Deque作为栈或者队列使用&#xff0c;但是一直都不知道Queue的作用&#xff0c;于是就直接官方…

亮相全国集群智能与协同控制大会,卓翼飞思无人智能科研方案成焦点

无人集群智能协同技术是人工智能发展的必然趋势&#xff0c;也是我国新一代人工智能的核心研究领域。为加强集群智能与协同控制需求牵引和对接、技术交流和互动&#xff0c;11月23-25日&#xff0c;由中国指挥与控制学会主办的第八届全国集群智能与协同控制大会在贵阳市隆重召开…

Oracle JDK(通常简称为 JDK)和 OpenJDK区别

Java 的开发和运行时环境主要由两种实现主导&#xff1a;Oracle JDK&#xff08;通常简称为 JDK&#xff09;和 OpenJDK。尽管它们都基于同一个代码库&#xff0c;但在一些关键点上有所区别。以下是详细的对比&#xff1a; 1. 基础代码 Oracle JDK&#xff1a; 基于 OpenJD…

损失函数分类

1. NLLLoss&#xff08;负对数似然损失&#xff09; 定义&#xff1a; 直接对预测的概率 p(yi) 的负对数求平均。通常配合 Softmax 使用&#xff0c;输入为对数概率。 优点&#xff1a; 对离散分类问题效果良好。更灵活&#xff0c;用户可以自行计算 Softmax。 缺点&#x…

vue3 数字滚动插件vue3-count-to

安装 npm i vue3-count-to -S 引入 import { CountTo } from vue3-count-to 使用 <countTo :startVal"0" :endVal"57.63" :decimals"0" :duration"3000"></countTo> 所有配置

CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)(前五道)

A. Shohag Loves Mod 翻译&#xff1a; Shohag 有一个整数 n。请帮他找出一个递增整数序列 &#xff0c;使得 在所有 的对上都满足。 可以证明&#xff0c;在给定的约束条件下&#xff0c;这样的序列总是存在的。 思路&#xff1a; 每个数为下标i*2-1&#xff08;注意这里下…

数据结构之二:表

顺序表代码&#xff1a;SData/SqList/SeqList.h Hera_Yc/bit_C_学习 - 码云 - 开源中国 链表相关代码&#xff1a;SData/ListLink/main.c Hera_Yc/bit_C_学习 - 码云 - 开源中国 leetcode相关代码leetcode/reverse_Link/main.c Hera_Yc/bit_C_学习 - 码云 - 开源中国 本文…

Adaboost集成学习 | Python实现基于NuSVR-Adaboost多输入单输出回归预测

目录 效果一览基本介绍程序设计参考资料效果一览 基本介绍 基于NuSVR-Adaboost多输入单输出回归预测python代码 NuSVR是一种支持向量回归(SVR)算法的变体,用于解决回归问题。SVR是一种监督学习方法,它用于预测连续目标变量,而不是分类标签。NuSVR在SVR的基础上引入了一个…

Vue.js --- 生命周期

1. 前言 在 Vue.js 中&#xff0c;生命周期是指一个 Vue 实例从创建到销毁的过程。Vue 提供了一系列的生命周期钩子&#xff08;lifecycle hooks&#xff09;&#xff0c;让开发者可以在不同的阶段执行特定的代码。了解这些生命周期钩子是构建 Vue 组件的基础&#xff0c;能够…

排序算法之选择排序篇

思想&#xff1a; 每次从未排序的部分找出最小的元素&#xff0c;将其放到已排序部分的末尾 从数据结构中找到最小值&#xff0c;放到第一位&#xff0c;放到最前面&#xff0c;之后再从剩下的元素中找出第二小的值放到第二位&#xff0c;以此类推。 实现思路&#xff1a; 遍…

hive的cascade使用解释

最近看到涉及到hive表字段新增&#xff0c;项目组其他人员让我add columns后加 cascade&#xff0c;这个我以前见到过&#xff0c;但是我一般没有用&#xff0c;也没出问题&#xff0c;那就研究下。 网上大多数的说法就是分区表加字段需要级联&#xff0c;原因是&#xff0c;你…

聊聊Flink:这次把Flink的触发器(Trigger)、移除器(Evictor)讲透

一、触发器(Trigger) Trigger 决定了一个窗口&#xff08;由 window assigner 定义&#xff09;何时可以被 window function 处理。 每个 WindowAssigner 都有一个默认的 Trigger。 如果默认 trigger 无法满足你的需要&#xff0c;你可以在 trigger(…) 调用中指定自定义的 tr…

docker部署nginx,并配置SSL证书

、拉取nginx镜像 docker pull nginx:latest 在此过程中会遇到网络的问题&#xff0c;导致镜像无法下载&#xff0c;这时候需要在服务器中配置下国内的镜像地址。下面包含近期最新的国内镜像&#xff0c;截至2024年11月27日&#xff1a; "https://<你的阿里云账号ID&…

OceanBase 大数据量导入(obloader)

现需要将源数据库&#xff08;Oracle|MySQL等&#xff09;一些表的海量数据迁移到目标数据库 OceanBase 中&#xff0c;基于常规 jdbc 驱动编码的方式涉及开发工作&#xff0c;性能效率也要看编码的处理机制。 OceanBase 官方提供了的 OceanBase Migration Service (OMS) 数据…

【Spring MVC】如何获取cookie/session以及响应@RestController的理解,Header的设置

前言 &#x1f31f;&#x1f31f;本期讲解关于SpringMVC的编程之参数传递~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废…

【详细介绍及演示】Flink之checkpoint检查点的使用

目录 一、介绍 二、 设置checkpoint检查点演示 1、 代码演示 2、测试代码效果 3、查看快照情况 ​编辑 三、在集群上运行 1、第一次运行 2、第二次运行 四、自定义检查点savePoint 1、提交一个flink job 打成jar包 2、输入一些数据&#xff0c;观察单词对应的数字的…