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

C++初阶:入门泛型编程(函数模板和类模板)

大致介绍了一下C/C++内存管理、new与delete后:C++初阶:C/C++内存管理、new与delete详解
我们接下来终于进入了模版的学习了,今天就先来入门泛型编程


文章目录

  • 1.泛型编程
  • 2.函数模版
    • 2.1概念
    • 2.2格式
    • 2.3函数模版的原理
    • 2.4函数模版的实例化
      • 2.4.1隐式实例化
      • 2.4.2显示实例化
    • 2.5 模板参数的匹配原则
  • 3.类模板
    • 3.1概念
    • 3.2格式
    • 3.3类模板的实例化


1.泛型编程

**泛型编程是一种编程范式,旨在编写可以适用于多种数据类型的通用代码。通过泛型编程,我们可以编写一次代码,然后将其应用于不同的数据类型,从而避免重复编写相似的代码 **

之前我们面对多种类型只能这样干:

int Swap(int& a, int& b)
{int temp = a;a = b;b = temp;
}void Swap(double& a, double& b)
{double temp = a;a = b;b = temp;
}int main()
{int a = 1, b = 2;double c = 1.1, d = 2.2;Swap(a, b);Swap(c, d);return 0;
}

使用函数重载虽然可以实现,但是有一下几个不好的地方:

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

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

现在就轮到泛型编程出场了:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

请添加图片描述


2.函数模版

2.1概念

函数模板是一种允许我们编写通用函数的工具。通过函数模板,我们可以定义一个函数,其中的某些类型可以是通用的,从而使函数能够处理多种数据类型。函数模板使用template关键字定义,并使用一个或多个类型参数来表示通用的类型。

2.2格式

template<typename T1, typename T2,......,typename Tn>//一个或多个
返回值类型 functionName(T parameter1, T parameter2, ...) {// 函数体
}
  • template <typename T>:使用template关键字定义函数模板,并在尖括号中指定一个或多个类型参数.
  • typename是用来定义模板参数关键字,也可以使用class
  • functionName:函数模板的名称。
  • T parameter1, T parameter2, ...:函数模板的参数列表,参数类型为通用的类型T

单模版参数:

template<class T>
void Swap(T& a, T& b)
{T temp = a;a = b;b = temp;
}

多模版参数:

template<class T ,class Y>
void print(T& a, Y& b)
{cout << a << " " << b << endl;
}int main()
{int a = 1;double b = 1.1;print(a, b);return 0;
}

请添加图片描述

2.3函数模版的原理

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

当使用函数模板时,编译器会根据传入的参数类型来实例化模板,并生成对应的函数。

还是这段代码:

template<class T>
void Swap(T& a, T& b)
{T temp = a;a = b;b = temp;
}int main()
{int a = 1, b = 2;double c = 1.1, d = 2.2;Swap(a, b);Swap(c, d);return 0;
}

请添加图片描述

转到反汇编看后发现:两处调用函数的地址不一样,这说明不是同一个函数

请添加图片描述

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用int类型使用函数模板时,编译器通过对实参类型的推演,将T确定为int类型,然后产生一份专门处理int类型的代码,对于字符类型也是如此

2.4函数模版的实例化

不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

2.4.1隐式实例化

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

template<class T>
T add(T& a, T& b)
{return a + b;
}int main()
{int a = 1, b = 2;int ab = add(a, b);double c = 1.1, d = 2.2;double cd = add(c, d);//这样会怎样呢?add(a, c);return 0;
}

add(a, c); 这样调用会怎么样呢 ?

该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型 通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,编译器报错

此时有两种处理方式:

  1. 用户自己来强制转化
template<class T>
T add(const T& a,const  T& b)
{return a + b;
}int main()
{int t1 = add(1, (int)2.2);//自己直接强制转换double t2 = add((double)1, 2.2);return 0;
}
  1. 使用显式实例化

2.4.2显示实例化

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

1.解决类型推测不同问题

template<class T ,class Y>
void print(T& a, Y& b)
{cout << a << " " << b << endl;
}template<class T>
T add(const T& a,const  T& b)
{return a + b;
}int main()
{int a1 = 1;double b1 = 1.1;int a = add<int>(a1, b1);//显示实例化double b = add<double>(a1, b1);print(a, b);return 0;
}

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

  1. 函数模版参数列表里没有通用类型
template<class T>
T* fun1(int n)
{return new T[n];
}int main()
{int* a = fun1<int>(10);//此时必须显示实例化,不然没有办法推测T是什么类型return 0;
}

2.5 模板参数的匹配原则

  1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
  2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
  3. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

3.类模板

3.1概念

**类模板允许我们创建通用的类,以存储和操作多种数据类型。类模板使用template关键字定义,并可以包含一个或多个类型参数 **

3.2格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
template<class T>
class Stack
{
public:Stack(int capacity = 3){cout << "调用了构造函数" << endl;_a = new T[capacity];_top = 0;_capacity = capacity;}~Stack(){cout << "~Stack()" << endl;delete _a;_a = nullptr;_top = -1;_capacity = 0;}
private:int* _a;int _top;int _capacity;
};int main()
{Stack<int> s1;Stack<double> s2;//之前我们都是使用typedef来改变,但是只能存在一个。现在不一样了return 0;
}

3.3类模板的实例化

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

int main()
{// Stack是类名,Stack<int>和Stack<double>才是类型Stack<int> s1;Stack<double> s2;return 0;
}

好啦,这次的内容就到这里啦。接下来进入stl的学习啦!!感谢大家支持~!

相关文章:

C++初阶:入门泛型编程(函数模板和类模板)

大致介绍了一下C/C内存管理、new与delete后&#xff1a;C初阶&#xff1a;C/C内存管理、new与delete详解 我们接下来终于进入了模版的学习了&#xff0c;今天就先来入门泛型编程 文章目录 1.泛型编程2.函数模版2.1概念2.2格式2.3函数模版的原理2.4函数模版的实例化2.4.1隐式实例…...

【RT-DETR有效改进】CARAFE提高精度的上采样方法(助力细节长点)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文给大家带来的CARAFE(Content-Aware ReAssembly of FEatures)是一种用于增强卷积神经网络特征图的上采样方法。其主要旨在改进传统的上采样方法(就是我们的Upsample)的性能。CARAFE的核心思想是:使用输…...

leetcode 27.移除元素(python版)

需求 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度…...

分布式场景怎么Join

背景 最近在阅读查询优化器的论文&#xff0c;发现System R中对于Join操作的定义一般分为了两种&#xff0c;即嵌套循环、排序-合并联接。 考虑到我的领域是在处理分库分表或者其他的分区模式&#xff0c;这让我开始不由得联想我们怎么在分布式场景应用这个Join逻辑&#xff…...

springboot2.7继承swagger knif4j

maven pom依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId><version>4.4.0</version></dependency> yml配置 knife4j:enable: trueopenapi:title: …...

C++ 实现单例模式

单例模式 单例模式确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 创建单一实例 怎么让某个类只能创建一个实例&#xff1f; 思路&#xff1a;将类的构造函数私有&#xff0c;然后提供一个静态方法访问对象。调用类内成员函数需要对象&#xff0c;但我们又无法…...

Java多线程--线程安全问题练习题

文章目录 &#xff08;1&#xff09;练习题1&#xff08;2&#xff09;练习题2&#xff08;3&#xff09;练习题3 现在咱们线程一共说了这么几件事情&#xff0c;如下&#xff1a; 具体文章见专栏。 接下来看几个练习题吧。 &#xff08;1&#xff09;练习题1 &#x1f30b;题…...

PHY6252低成本Mesh组网蓝牙芯片

超低成本MESH组网蓝牙芯片PHY6252蓝牙Mesh组网简介 蓝⽛Mesh⽹络使⽤&#xff0c;依赖于低功耗蓝⽛(BLE)。低功耗蓝⽛技术是蓝⽛Mesh使用的无线通信协议栈&#xff0c;蓝牙BR/EDR能够与实现一台设备到另一台设备的连接和通信&#xff0c;建立“一对一”的关系&#xff0c;大多数…...

红外图像中两点校正的增益系数与偏置系数的计算公式推导

增益系数&#xff08;K&#xff09; 根据两个温度下的响应值&#xff0c;可求得各响应单元的响应曲线&#xff08;即斜率&#xff09;&#xff0c;累加所有曲线的斜率求平均斜率值。 平均斜率值与各响应单元的斜率的比值即为该单元的K增益系数。结论&#xff1a;某单元的增益系…...

C++/MFC:在窗体Form(Dialog)中多个编辑框时,在输入时将回车解释为TAB键,将输入焦点移到下一个编辑框的方法

很多时候&#xff0c;为了输入方便&#xff0c;常用的做法&#xff0c;就是将回车键解释为将输入焦点移动到下一个编辑框中。就像是我的VxTerm中的快速连接输入一样&#xff1a; VxTerm是一个国产化替代的SSH工具&#xff0c;可以从本站的资源中免费下载并且免费使用&#xff…...

鸿蒙南向开发——GN快速入门指南

运行GN(Generate Ninja) 运行gn&#xff0c;你只需从命令行运行gn&#xff0c;对于大型项目&#xff0c;GN是与源码一起的。 对于Chromium和基于Chromium的项目&#xff0c;有一个在depot_tools中的脚本&#xff0c;它需要加入到你的PATH环境变量中。该脚本将在包含当前目录的…...

PyCharm常用快捷键和设置

Ctrl Space 基本的代码完成&#xff08;类、方法、属性&#xff09; Ctrl Alt Space 快速导入任意类 Ctrl Shift Enter 语句完成 Ctrl P 参数信息&#xff08;在方法中调用参数&#xff09; Ctrl Q 快速查看文档 F1 外部文档 Shift F1 外部文档…...

Unity - 调节camera物理相机参数(HDRP)

在 “Hierarchy” 右键 -> Volume -> Global Volume new 一个 profile, 设置Mode为Pysical Camera 再点击camera组件&#xff0c;这时候设置 ISO、Shutter Speed、Aperture等参数值还会有效。...

@JsonIgnore的使用及相关问题的解决

目录 1 前言 2 对比及其使用方法 3 遇到的相关问题及解决方法 1 前言 在我们编写的后端项目中&#xff0c;有时候可能需要将某个实体类以JSON格式传送给前端&#xff0c;但是其中可能有部分内容我们并不想传送&#xff0c;这时候我们选择将这部分内容变成Null&#xff0c;这…...

万户 ezOFFICE SendFileCheckTemplateEdit.jsp SQL注入漏洞

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…...

自建DNS劫持服务器,纯内网劫持PS5,屏蔽更新,自动hen

背景&#xff1a;目前PS5首次折腾必须要连外网&#xff0c;还要改DNS&#xff0c;除非使用ESP8266/32&#xff0c; 本文的方法是完全不改DNS&#xff0c;不使用ESP8266,不连接外网的情况下自动折腾 能实现什么&#xff1a; 1.折腾全程不连接外网 2.完全自建hen服务器&#xff…...

C语言王道第八周一题

Description 初始化顺序表&#xff08;顺序表中元素为整型&#xff09;&#xff0c;里边的元素是 1,2,3&#xff0c;然后通过 scanf 读取一个元素&#xff08;假如插入的是 6&#xff09;&#xff0c;插入到第 2 个位置&#xff0c;打印输出顺序表&#xff0c;每个 元素占 3 个…...

探索1688店铺所有商品API接口:一键获取海量数据,开启商业智能新篇章

1688店铺所有商品API接口技术详解 一、概述 1688店铺所有商品API接口是阿里巴巴提供的一套应用程序接口&#xff0c;允许第三方开发者获取指定1688店铺下的所有商品信息。通过使用这个接口&#xff0c;开发者可以获取到店铺内所有商品的列表、详情、属性等信息&#xff0c;从…...

使用Win32API实现贪吃蛇小游戏

目录 C语言贪吃蛇项目 基本功能 需要的基础内容 Win32API 介绍 控制台程序部分指令 设置控制台窗口的长宽 设置控制台的名字 控制台在屏幕上的坐标位置结构体COORD 检索指定标准设备的句柄&#xff08;标准输入、标准输出或标准错误&#xff09; 光标信息结构体类型CONSOLE_CUR…...

力扣0114——二叉树展开为链表

[二叉树展开为链表] 难度&#xff1a;中等 题目描述 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

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

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

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...