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

【C++】模版:范式编程、函数模板、类模板

目录

一.范式编程

二.函数模板

1.概念与格式

2.原理

3.实例化

4.匹配规则

三.类模板


一.范式编程

在写C++函数重载的时候,可能会写很多同一类的函数,例如交换函数:

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;
}

针对不同的类型(int,double,char...)要写相似但不同的函数,如上代码就存在以下问题:

  • 重载函数仅仅是类型不同,但只有有新类型出现,就必须增加对应的函数,代码复用率比较低
  • 同时代码的可维护性也很低,一个函数出错需要修改,其余的重载也都需要进行修改

为了应对以上问题,模版应运而生。就像活字印刷中的模板一样,根据模板能够印出对应的字,根据颜料的不同,又能印出颜色不同的字,放在C++中也是同理,存在模板这样一个模具,在这个模具中填入不同材料(类型),得到不同的结果,这就是范式编程。

范式编程:编写与类型无关的通用代码,是代码复用的一种手段,模板是范式编程的基础。同时模板又有函数模板和类模板。 

二.函数模板

1.概念与格式

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

 使用的格式为:

template<class T1,class T2,......>

返回值类型 函数名(参数列表){    函数主体    }

template就是使用模板的关键字,class可以使用typename替代,但不能使用struct替代,并且class和typename可以混用,可以出现template<class T1,typename T2>的情况,T1,T2...代表不同的类型,可以在函数的实现中使用。

 具体到交换函数的函数模板就是这样:

template<typename T>
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}

可以发现,T可以是int,double,char等不同类型,对该模板传入不同的类型,就会得到不同的特定类型函数,这样就大大增加了代码复用率。 

小练习:

其中4,6,7是正确声明,尤其注意7这样的class,typename混用是允许的。 

2.原理

函数模板本质而言就是一个蓝图,它本身并不是函数。就像类和对象的区别一样,类是图纸,对象才是实际建造起来的房子。函数模板是编译器产生特定类型具体函数的模具,模板只是将本该我们做的重复事情交给了编译器。

 在编译器编译阶段,对于模版函数的使用,编译器会根据传入的实参类型来推导生成对应的特定类型的函数,也就是对于不同类型,编译器会根据模板自动生成专门的函数来使用,注意这里调用的函数不是同一个函数

3.实例化

当使用不同类型的参数来使用函数模板时,就被称为函数模板的实例化。函数模版的实例化分为隐式实例化和显示实例化。

隐式实例化:让编译器根据实参推导模板参数的实际类型

template<class T>
T Add(const T& x, const T& y)
{return x + y;
}int main()
{int a1 = 10, a2 = 20;double d1 = 10.1, d2 = 20.1;//a1,a2都是int类型,因此编译器自动推导模板中T为int类型cout << Add(a1, a2) << endl;//同理,此时推导T为double类型cout << Add(d1, d2) << endl;
}

 然而,也会存在编译器无法推导的情况,例如此时,c1和c2类型不相同,c1为int,c2为double,那么此时编译器应该推导T为int还是double呢?编译器不知道,因此报出了错误。

 此时可以使用多参数模板解决,就是在template声明模板时,再加一个类型T2,这样就能进行合适的推导了。当然,也可以使用显示实例化:

显示实例化:直接告诉编译器这个类型T是什么,此时哪怕实参不是类型T,也会走隐式类型转换

例如此时若指定T为int类型,那么double类型的c2就会隐式转换为20,double也是同理

4.匹配规则

  • 一个非模板函数可以和另外一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
  • 对于非模板函数和同名函数模板,如果其他条件都相同,那么调用时会优先调用非模板函数,从而不会实例化一个模板函数,反之,若模板可以实例化一个更匹配的函数,那么就会选择模板
//非模板函数,适用于int类型相加
int Add(int a, int b)
{return a + b;
}//函数模板,适用于相加
template <class T1, class T2 >
T1 Add(T1 a, T2 b)
{return a + b;
}int main()
{Add(10, 10);//调用非模板Add(10, 10.1);//调用模板return 0;
}

注意:模板函数不允许自动类型转换,但普通函数是可以进行自动类型转换的。 

三.类模板

类模板和函数模板类似,格式为:

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

 例如声明一个简单的Stack栈的类模板:

template <class T>
class Stack
{
public:Stack(int capacity = 4){_arr = new T[capacity];_size = 0;_capacity = capacity;}void Push(const T& data) {if (_size == _capacity){int capacity_s = _capacity * 2;T* tmp = new T[capacity_s];memcpy(tmp, _arr, sizeof(capacity_s));_arr = tmp;_capacity = capacity_s;}_arr[_size++] = data;}private:T* _arr;int _size;int _capacity;
};int main() 
{//实例化模板Stack<int> s1;//intStack<double> s2;//doubles1.Push(1);s1.Push(2);s2.Push(2.15);s2.Push(2.16);}

那么这跟直接实现Stack类比较有什么好处呢?在直接实现的stack中,通常使用typedef数据类型来使用,可这也间接限制了栈储存不同类型数据的情况,若同时需要一个存放int类型一个存放double类型的栈,直接实现就很难了,需要单独去实现两个不同类型的stack,而模板就很好的解决了这一问题,直接传入不同的类型来实例化针对不同数据类型的栈:

// Stack是类名,Stack<int>才是类型Stack<int> st1;    // int类型的栈Stack<double> st2; // double类型的栈

接下来是一些类模板的练习题,加深对模板的理解:

下面有关C++中为什么用模板类的原因,描述错误的是? ( )

答案:C,模板运行时不检查数据类型,也不保证类型安全,相当于类型的宏替换

 下列关于模板的说法正确的是( )

答案:D,对于A而言,前文在隐式类型转换时给出的Add(c1,c2)就是显然的报错,编译器无法自动推导,此时不能省略;对于B而言,类模板重点在后模板二字,是未实例化的模具,而模板类是根据 类模板 这个模具做出的类,是类模板实例化得到的具体类;对于C而言,template<class T, size_t N>这样的存在是允许的,虚拟类型指的是class T,而size_t N并非虚拟类型

 下列描述错误的是( )

答案:D,模板类是一个家族,编译器的处理会分别进行两次编译,其处理过程跟普通类不一样

相关文章:

【C++】模版:范式编程、函数模板、类模板

目录 一.范式编程 二.函数模板 1.概念与格式 2.原理 3.实例化 4.匹配规则 三.类模板 一.范式编程 在写C函数重载的时候&#xff0c;可能会写很多同一类的函数&#xff0c;例如交换函数&#xff1a; void Swap(int& left, int& right) {int temp left;left r…...

验证图片旋转

最近在使用百度图片翻译时遇到一个问题&#xff0c;就是图片会翻转90&#xff0c;经与百度沟通&#xff0c;发现是原始图片中有个旋转参数引起的。 于是写个demo验证一下。 // 获取元数据中的旋转方向 func getOrientation() int {//打开图像文件f, err : os.Open("image…...

宏景eHR /ajax/ajaxService SQL注入漏洞复现

0x01 产品简介 宏景eHR人力资源管理软件是一款人力资源管理与数字化应用相融合,满足动态化、协同化、流程化、战略化需求的软件。 0x02 漏洞概述 宏景eHR /ajax/ajaxService 接口处存在SQL注入漏洞,,未经身份验证的远程攻击者通过利用SQL注入漏洞配合数据库xp_cmdshell可…...

从源码看 Redis:深入理解 redisDb 和 redisObject

Redis 是一个广泛使用的内存数据库&#xff0c;以其高性能和丰富的数据结构而闻名。不同于磁盘数据库&#xff0c;磁盘数据库将数据读取到文件中维护&#xff0c;而内存数据库将数据存储在内存中&#xff0c;意味着其想要维护数据&#xff0c;必须在代码中维护一个保存数据的结…...

unity中实现流光效果——世界空间下

Properties{_MainTex ("Texture", 2D) "white" {}_FlowColor ("Flow Color", Color) (1, 1, 1, 1) // 流光颜色_FlowFrequency ("Flow Frequency", Float) 1.0 // 流光频率_FlowSpeed ("Flow Speed", Float) 1.0 // 流光…...

项目经验分享:用4G路由器CPE接海康NVR采用国标GB28181协议TCP被动取流一段时间后设备就掉线了

最近我们在做一个生态化养殖的项目时&#xff0c;发现一个奇怪的现象&#xff1a; 项目现场由于没有有线网络&#xff0c;所以&#xff0c;我们在现场IPC接入到海康NVR之后&#xff0c;再通过一款4G的CPE接入到天翼云的国标GB28181视频平台&#xff1b;我们采用UDP协议播放NVR…...

【RabbitMQ】RabbitMQ不公平分发_预取值

一、不公平分发 1、简介 RabbitMQ中的不公平分发&#xff08;Unfair Dispatch&#xff09;是指当多个消费者&#xff08;Consumers&#xff09;同时订阅同一个队列&#xff08;Queue&#xff09;时&#xff0c;消息的分发机制并非严格平均或公平&#xff0c;而是基于某些条件…...

最新AI模型使用指南和模型

市面上最好的AI大模型 OpenAI GPT-4&#xff1a; 概述&#xff1a;GPT-4 是 OpenAI 发布的最新一代大型语言模型&#xff0c;具备更强的理解和生成自然语言的能力。特点&#xff1a; 强大的文本生成和理解能力。支持多语言处理。可用于各种应用场景&#xff0c;如对话生成、内容…...

数据结构之八大基本排序方法

在数据结构中&#xff0c;排序是一个重要的操作&#xff0c;它有助于提高数据的可读性和可操作性。排序算法有多种&#xff0c;各有优缺点&#xff0c;适用于不同的场景。以下是八大经典排序算法的介绍&#xff1a; 1. 冒泡排序&#xff08;Bubble Sort&#xff09; 原理&…...

《Milvus Cloud向量数据库指南》——什么是高可用:深入理解数据库系统中的高可用性架构

什么是高可用:深入理解数据库系统中的高可用性架构 在信息技术日新月异的今天,高可用性(High Availability,简称HA)已成为衡量一个系统,尤其是数据库系统稳定性和可靠性的重要标准。高可用性的核心目标在于确保系统能够持续不断地提供服务,最大限度地减少因维护活动、硬…...

C++ | Leetcode C++题解之第319题灯泡开关

题目&#xff1a; 题解&#xff1a; class Solution { public:int bulbSwitch(int n) {return sqrt(n 0.5);} };...

C# 使用 NLog 输出日志到文件夹

在项目中使用 NuGet 安装 NLog 包以及 NLog.Config 包 配置 nlog.config 在项目的根目录下创建一个 Nlog.config 文件&#xff08;如果还没有&#xff09;&#xff0c;然后添加如下配置&#xff1a; <?xml version"1.0" encoding"utf-8" ?> <…...

node.js使用NodeMachineID 生成唯一UUID和注意事项

node-machine-id用于获取或生成唯一的机器ID 如何使用 const { machineId, machineIdSync } require(node-machine-id) JSON.stringify(machineIdSync({original: true})) ;方法&#xff1a; machineIdSync 此函数同步获取操作系统本机UUID/GUID&#xff0c;默认情况下进行哈…...

AI大模型在数据治理中的应用

目前&#xff0c;企业的数据治理工作以人工实施为主&#xff0c;其中一些重复性较强的工作&#xff0c;如&#xff1a;数据标准制定和映射、元数据信息完善、数据目录挂载等&#xff0c;需要消耗大量的人力和时间成本&#xff0c;这给本来就难以量化业务价值的治理工作的顺利推…...

【初学人工智能原理】【12】循环:序列依赖问题

前言 本文教程均来自b站【小白也能听懂的人工智能原理】&#xff0c;感兴趣的可自行到b站观看。 代码及工具箱 本专栏的代码和工具函数已经上传到GitHub&#xff1a;1571859588/xiaobai_AI: 零基础入门人工智能 (github.com)&#xff0c;可以找到对应课程的代码 正文 对于…...

【QT】无法打开QT的ui文件,出现闪退情况

打开qt的ui文件出现闪退的情况&#xff1a; 解决办法&#xff1a;点击扩展-Qt VS Tools-Options 找到Qt General中的Qt Designer 的Run in detached window改为True。...

三、Spring-WebFlux实战案例-流式

目录 一、springboot之间通讯方式 1. 服务端 (Spring Boot) 1.1 添加依赖 1.2 控制器 2. 客户端 (WebClient) 2.1 添加依赖 2.2 客户端代码 3. 运行 二、web与服务之间通讯方式 1、服务端代码 2、客户端代码 3、注意事项 三、移动端与服务端之间通讯方式…...

html+css 实现hover双层按钮

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…...

SPIFFS与LittleFS的对gz文件格式的区别

SPIFFS 只能安装在Arduino上。LittleFS支持Arduino IDE和VScode的 PlatformIO。 SPIFFS serveStatic: server.serveStatic("/", SPIFFS, "/") 负责提供 SPIFFS 文件系统中的文件。您可以在 SPIFFS 上放置 .gz 文件&#xff0c;并该方法将自动处理它们。 …...

STM32L051K8U6-开发资料

STM32L051测试 &#xff08;四、Flash和EEPROM的读写&#xff09;-云社区-华为云 (huaweicloud.com) STM32L051测试 &#xff08;四、Flash和EEPROM的读写&#xff09; - 掘金 (juejin.cn) STM32L0 系列 EEPROM 读写&#xff0c;程序卡死&#xff1f;_stm32l0片内eeprom_stm3…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...