模板和泛型编程(上)

news2024/9/21 20:36:44

目录

  • 函数模板
    • 泛型编程
    • 函数模板概念及原理
    • 函数模板的实例化
    • 函数模板的匹配原则
  • 类模板
    • 类模板实例化

函数模板

泛型编程

泛型编程(Generic Programming)最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库。所谓通用的标准容器库,就是要能够做到,比如用一个List类存放所有可能类型的对象这样的事;泛型编程让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。泛型即是指具有在多种数据类型上皆可操作的含义,与模板有些相似。
编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础

void Swap(int& left, int& right) {
	int temp = left;
	left = right;
	right = temp;
}
void Swap(double& left, double& right) {
	double temp = left;
	left = right;
	right = temp;
}
void Swap(char& left, char& right) {
	char temp = left;
	left = right;
	right = temp;
}

利用C++函数重载的特性可以写一个通用的交换函数,可以交换数据类型不同的数据,但这样代码的复用率比较低,只要有新类型出现时,就需要增加对应的函数,而且极容易出错。所以,c++基于重载这一项机制,实现了模板编程,模板可以针对不同类型,来实现相应的操作。

函数模板概念及原理

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

用法

template<typename T1, typename T2,…,typename Tn>
typename即类型名,也可以用class替代,这里的class指的是类型,不能用struct替换

在这里插入图片描述
可以发现三种类型的数据都被交换了。

原理
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。
通过汇编代码可以看到编译器会通过我们给的不同类型参数的函数,然后在底层生成一个该类型的模板函数,并调用该函数。
在这里插入图片描述

函数模板的实例化

隐式实例化
当我们用不同类型的参数使用函数模板时,就称为函数模板的实例化。

template<class T>
T Add(const T& num1, const T& num2)
{
	return num1 + num2;
}
int main()
{
	int a1 = 10, a2 = 100;
	double d1 = 1.1, d2 = 3.14;
	Add(a1, a2);
	Add(d1, d2);

//编译报错
//通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,因为需要通过参数推演出对应类型,但是此时就无法推演出到底是将T推演成double还是将T推演成int
//Add(a1, d1);

// 此时有两种处理方式:1. 强制转化 2. 使用显式实例化
	Add(a, (int)d);
	return 0;
}

显示实例化
在函数名后的<>中指定模板参数的实际类型

int main() {
	 int x = 10;
	 double y = 3.14159;
	 // 显式实例化
 	 Add<int>(x, y);  //参数类型不一样,编译器会进行隐式类型转换
 	 add<double>(x, y);
	 return 0; 
 }

函数模板的匹配原则

  1. **一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数 **
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版本,调用模板函数
}
  1. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
// 专门处理int的加法函数
int Add(int left, int right) {
	return left + right;
}

// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right) {
	return left + right;
}

void Test()
{
	Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
	Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
}

模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

类模板

用法

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

这里的Vercor不是一个具体的类,他是类模板,通过这个模板来识别参数的类型并生成对应的模板类。所以可以理解为类模板是一个类家族,模板类是通过类模板实例化的具体类,T可以实例化为int也可以实例化为string类。

template<class T>
class Vector
{
public :
	Vector(int capacity = 8)
	: _cur(new T[capacity])
	, _size(0)
	, _capacity(capacity)
	{}
// 使用析构函数演示:在类中声明,在类外定义。
	~Vector();
	void PushBack(const T& data);
	void PopBack();
private:
	T* _cur;
	int _size;
	int _capacity;
};
// 类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{
	if(_cur)
	delete[] _cur;
	_size = _capacity = 0;
}

类模板实例化

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

// stack类名,stack<int>才是类型
stack<int> s1;
stack<double> s2;

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

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

相关文章

猿创征文|Python迭代器、生成器、装饰器、函数闭包

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 Python迭代器、生成器、装饰器、函数闭包1. 迭代器 iterator☞迭代器协议☞Python中的for循环2. 生成器…

C语言qsort()函数针对:整型、单个字符、字符串、结构体,超详细讲解(多维度分析举例,小白一看就懂!!!!!)

目录 一、前言 二、qsort()函数 &#x1f351;qsort()函数简介 &#x1f349;qsort()函数中整型、double型、字符型的应用 &#x1f4a6;整型 &#x1f4a6; double型 &#x1f4a6;字符排序 &#x1f34e;qsort()函数在字符串中的应用 &#x1f4a6;在字符串中按首字母…

Android NDK开发基础

文章目录cmake语法基础cmake添加日志&#xff1a;cmake增加宏字符串比较cmake在build.gradle中传递编译参数到cmake通过javah生成native对应的c头文件jni和java之间字符串的相互操作JavaVM和JNIEnv字符串的编码native方法静态注册和动态注册静态注册动态注册extern cC中STATIC和…

SpringCloud Alibaba-Sentinel保姆级教程

文章目录1、Sentinel前奏1.1、服务雪崩效应1.2、常见容错方案1、隔离2、超时3、限流4、熔断5、降级1.3、常见容错组件1、Hystrix2、Resilience4J3、Sentinel2、Sentinel入门2.1、什么是Sentinel2.2、实战编码1、安装Sentinel服务端2、微服务引入Sentinel2.3、Sentinel流控模式1…

YOLOv5蒸馏 | 知识蒸馏理论篇 | 1/2

之前在《一文搞懂【知识蒸馏】【Knowledge Distillation】算法原理》这篇文章中介绍过一些知识蒸馏的原理,这篇博文将会着重介绍目标检测领域的知识蒸馏原理。 文章目录 1.《Object detection at 200 Frames Per Second》1.1 蒸馏难点1.2 蒸馏损失1.3 实验结果2. 《Learning E…

计算机毕业设计ssm+vue基本微信小程序的体检预约小程序

项目介绍 我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;体检预约系统小程序被用户普遍使用&#xff0c;为方便用户…

【前端】CSS(1) —— CSS的基本语法和一些简单的选择器

JavaEE传送门JavaEE 网络原理——网络层与数据链路层 【前端】HTML入门 —— HTML的常见标签 目录CSS基本语法注释引入方式内部样式内联样式外部样式代码风格样式格式样式大小写空格规范CSS 选择器标签选择器类选择器id 选择器通配符选择器复合选择器后代选择器子选择器并集选…

文件包含漏洞和hash破解

介绍 Windows是当今世界最主要的操作系统&#xff0c;因为它易于使用的GUI可访问性。大约85%的市场份额已成为攻击的关键操作系统。此外&#xff0c;大多数组织使用Active Directory来设置其Windows域网络。微软聘请NTLM&#xff08;New Technology LAN Manager&#xff09;和…

Pico Neo3 4VR游戏下载地址及十大好玩游戏推荐

大家好&#xff0c;杰克今天为大家分享的是VR一体机游戏。 说到VR一体机&#xff0c;我们首先想到的一定是国产之光pico啦&#xff0c;picovr被认为是国内最被看好的VR一体机&#xff0c;有望在国内取代红极一时的OculusQuest&#xff0c;填补这块市场的空白。OculusQuest将6D…

#Primavera Unifier:关于零代码/低代码平台特点【2/3】

在之前对Unifier的介绍中&#xff0c;我提到了Unifier应用的一个非常关键的特征&#xff0c;及零代码快速配置使用&#xff0c;而为了更好的介绍Oracle Primavera Unifier 的零代码特点&#xff0c;以下我将通过3篇内容来逐一介绍零代码/低代码平台的特点。 前面介绍到了零代码…

Opencv项目实战:14 手势控制音量

目录 0、项目介绍 1、项目展示 2、项目搭建 3、项目的代码与讲解 4、项目资源 5、项目总结 0、项目介绍 本篇与上一篇有很多联系&#xff0c;大家可以看看这篇Opencv项目实战&#xff1a;13 手部追踪&#xff0c;我们将根据上一节的内容&#xff0c;进行一个拓展。本篇你…

AtCoder Beginner Contest 275 【E】【F】

E - Sugoroku 4 【概率dp】 题意&#xff1a; 对于每个样例&#xff0c;读入n&#xff0c;m&#xff0c;k。 一维数轴&#xff0c;你现在在0这个点上&#xff0c;目标是到达n这个点&#xff0c;你有k次掷骰子的机会&#xff0c;每次可能等概率的掷出1~m的任意一个数字&#xff…

面了一个4年经验的测试工程师,自动化都不会也要15k,我真是醉了...

在深圳这家金融公司也待了几年&#xff0c;被别人面试过也面试过别人&#xff0c;大大小小的事情也见识不少&#xff0c;今天又是团面的一天&#xff0c; 一百多个人都聚集在一起&#xff0c;因为公司最近在谈项目出来面试就2个人&#xff0c;无奈又被叫到面试房间。 整个过程…

.NET Core HttpReports 监控

HttpReports 基于.NET Core 开发的APM监控系统&#xff0c;使用MIT开源协议&#xff0c;主要功能包括&#xff0c;统计, 分析, 可视化&#xff0c; 监控&#xff0c;追踪等&#xff0c;适合在中小项目中使用。 语雀&#xff1a;https://www.yuque.com/httpreports/docs/uyaiil …

SQL注入之绕过is_numeric过滤

目录预备知识PHP常用的过滤类函数is_numeric()函数介绍实验目的实验环境实验步骤一通过源代码审计&#xff0c;发现临时文件实验步骤二通过分析源代码的执行逻辑&#xff0c;了解程序的功能&#xff0c;发现程序中的安全漏洞实验步骤三绕过过滤函数实现SQL注入预备知识 PHP常用…

Linux进程信号

文章目录什么是信号signal函数的功能&#xff08;捕捉信号后自己处理&#xff09;Core Dump&#xff08;核心转储&#xff09;kill&#xff0c;raise&#xff0c;alarm系统调用再度理解OS给进程发送信号信号集操作函数自定义捕捉详解什么是信号 生活中的信号&#xff1a;闹钟&…

0083 环形链表

package LinkedList_; /* * 单向环形链表应用场景——约瑟夫问题 * 设编号为1&#xff0c;2....n的n个人围成一圈&#xff0c;约定编号为k&#xff08;1<k<n&#xff09;的人从1开始报数&#xff0c;数到m的人出列&#xff0c; * 它的下一位又从…

黑胶歌曲没权限,还好我会Python,一分钟一个歌单,硬盘有点不够用了~

今日份Python白嫖人生苦短&#xff0c;我用Python一、你需要准备1、环境2、模块二、效果展示三、代码展示四、写在最后人生苦短&#xff0c;我用Python 人之初&#xff0c;喜白嫖。大家都喜欢白嫖&#xff0c;我也喜欢&#xff0c;那么今天就来试试怎么白嫖抑云~ 我不是&#…

React面向组件编程(定义组件,组件三大核心属性,组件事件处理、组件收集表单数据、高阶函数和函数的柯里化)

目录 一、React中定义组件 1、函数式组件 2、类式组件 二、组件三大核心属性 1、组件三大核心属性1: State(状态) 2、组件三大核心属性2: props 3、组件三大核心属性3: ref 三、组件事件处理 1、事件处理 四、组件收集表单数据 1、受控组件 2、非受控组件 五、高阶函…

【数据结构】算法的时间复杂度和空间复杂度

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f40c; 个人主页&#xff1a;蜗牛牛啊 &#x1f525; 系列专栏&#xff1a;&#x1f6f9;初出茅庐C语言、&#x1f6f4;数据结构 ☀️ 学习格言&#xff1a;眼泪终究流不…