如何编写一个通用的函数?

在这里插入图片描述

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏1: 🍔🍟🌯C语言初阶
🐻推荐专栏2: 🍔🍟🌯C语言进阶
🔑个人信条: 🌵知行合一
金句分享:
✨你要狠下心来去努力,努力变成一个很厉害的人.✨

前言

本文主要讲解如何使用简单的模板,了解模板的原理以及基本知识.

目录

  • 前言
  • 一、函数模板
    • (1)函数模板的格式
    • (2)函数模板的原理(重点)
    • (3)模板参数的显示实例化
    • (4)模板匹配
  • 二、类模板

一、函数模板

模板的作用:

C++模板的作用是支持泛型编程。==泛型编程=是一种编程范式,它只考虑算法或数据结构的抽象,而不考虑具体的数据类型。通过使用模板,可以编写一种通用的算法或数据结构,而不需要为每种数据类型都编写一遍相关代码。模板可以用于函数、类、结构体等地方,以实现通用的算法和数据结构。使用模板可以提高代码的复用性和可读性,减少代码的重复编写。

示例:实现一个交换函数.

使用模板之前:

void swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}
void swap(double& a, double& b)
{double tmp = a;a = b;b = tmp;
}void swap(char& a, char& b)
{char tmp = a;a = b;b = tmp;
}void test1()
{//交换整形int a = 2, b = 3;cout << "a=" << a << "  " << "b=" << b << endl;swap(a, b);cout << "a=" << a << "  " << "b=" << b << endl;//交换字符型char c1 = 'd', c2 = 'f';cout << "c1=" << c1 << "  " << "c2=" << c2 << endl;swap(c1, c2);cout << "c1=" << c1 << "  " << "c2=" << c2 << endl;//交换...
}

上述实现过程中使用函数重载实现.但是函数重载会有一些不合适的问题.

  1. 函数重载只是重载的函数类型不同,代码复用率比较低,对于一个新的类型又要增加新的函数.
  2. 由于功能基本一样,只是类型不同,导致代码的可维护性比较,一个出错可能所有的重载均出错,均要修改.

这时,函数模板就派上用场了.

(1)函数模板的格式

template<typename T1, typename T2,......,typename Tn>
返回值类型 + 函数名 +(参数列表){}
其中,typename 可以使用class代替,不能使用struct代替.

示例:使用模板后的通用交换函数.

template <class T>//模板
void swap(T& a, T& b)//T会根据传参的对象进行推导为相应的类型
{T tmp = a;a = b;b = tmp;
}
void test1()
{//交换整形int a = 2, b = 3;cout << "a=" << a << "  " << "b=" << b << endl;swap(a, b);cout << "a=" << a << "  " << "b=" << b << endl;//交换字符型char c1 = 'd', c2 = 'f';cout << "c1=" << c1 << "  " << "c2=" << c2 << endl;swap(c1, c2);cout << "c1=" << c1 << "  " << "c2=" << c2 << endl;//交换...
}

(2)函数模板的原理(重点)

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

这就类似于古代的印刷术,如果每本书都需要手写,那效率是否太低了,还有各种情况可能会出错.但是印刷术的使用,就可以使用模具生成.
在这里插入图片描述

函数模板的原理是通过将类型参数化,使函数能够在编译时根据实际参数的类型推断生成具体的函数实例。编译器会根据调用函数时的参数类型,实例化出适合该类型的函数版本。

比如:
当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码.当用int类型使用函数模板时,编译器通过对实参类型的推演,将T确定为int类型,然后产生一份专门处理int类型的代码.如上图所示.

(3)模板参数的显示实例化

上面我们实现的交换函数,模板根据传参时不同的参数,自动推演出函数参数的实际类型.我们称这类通过编译器进行自动推导的实例化模板参数称为模板参数的隐式实例化.

那什么是显示实例化呢?

template <typename T>
T add(const T& a, const T& b)
{return a + b;
}
void test1()
{int a = 2, b = 3;double d1 = 2.5, d2 = 4.1;cout << add(a, b) << endl;cout << add(d1, d2) << endl;//下面这句会报错,因为一个模板参数无法在一个函数中实例化为2个不同类型的参数,一个int,一个double//cout << add(a, d2) << endl;
}

一个函数模板参数在同一个函数中,无法被识别为不同的两个实例类型参数,当编译器推导出aint时,又推出d2double类型,则编译器陷入两难.

就好比:
int:妈妈说今天不许出去玩!
double:爸爸说今天可以出去玩!
编译器:我听谁的.

解决方案:

直接将参数先强转为一样的,当模板函数接收到参数时,就只有一样的结果了.

	//解决方法1:传参时将其中不同的参数强转,使参数们相同cout << add(a, (int)d2) << endl;cout << add((double)a, d2) << endl;

模板参数的显示实例化:

让爸妈先商量好听谁的.

	//解决方法2:显示指定模板的参数cout << add<int>(a, d2) << endl;	//听妈妈的cout << add<double>(a, d2) << endl;	//听爸爸的

我们应当是考虑如何在调用时采取不同的调用方式去满足我们的需求,千万不要想着去修改模板函数的返回值,参数使他们固定生成,那模板就不通用了,而且不是什么时候我们都可以去修改模板的.
错误示例:

template <typename T>
T add(const T& a, const int& b)//直接修改参数,进行固定
{return a + b;
}

(4)模板匹配

对于函数名相同的非模板函数模板函数同时存在时,编译器会优先选择非模板函数.除非模板可以产生更好的匹配函数,才会选择模板.

编译器:有现成的为啥不用.

void swap(double& a, double& b)
{double tmp = a;a = b;b = tmp;
}
//template <class  T>
template <typename  T>//函数模板
void swap(T& a, T& b)
{T tmp = a;a = b;b = tmp;
}
void test1()
{//交换doubledouble d1 = 2.5, d2 = 4.5;//非模板函数和模板函数同时存在时,编译器优先选择非模板函数,有现成的为啥不用?非得自己去再模具刻一个?swap(d1, d2);cout << "d1=" << d1 << "  " << "d2=" << d2 << endl;//交换整形int a = 2, b = 3;//没有现成的非模板函数,则编译器调用模板函数去实例化一份swap(a, b);cout << "a=" << a << "  " << "b=" << b << endl;
}

交换double型数据时,会调用void swap(double& a, double& b)函数,因为有现成的可以调用.
交换int整形时,则会调用模板函数void swap(T& a, T& b),实例化生成int型的函数.

在这里插入图片描述
小知识:
模板函数不允许自动类型转换,但普通函数可以进行自动类型转换.
因为模板函数的参数是通过参数类型进行推导的.

二、类模板

类模板的格式

template <typename T>
class A
{//成员
}

类模板在后续学习STL时候会具体介绍,目前了解一下即可,使用方法与函数模板类似,这里就不过多介绍了.

template <typename T>
class A
{
public:A(size_t capacity = 10): _data(new T[capacity]), _size(0), _capacity(capacity){}void push_back() {//...}~A(){delete _data;_size = 0;_capacity = 0;}private:T* _data;size_t _size;size_t _capacity;
};void test3()
{A<int> a1;			//实例化为存储int数据的类A<double> a2;		//实例化为存储double数据的类
}

本文只是对模板的初步了解,后续会遇到更加复杂的模板,比如多参数的模板等,知识一点点的学,不求速成,坚持一点点的积累,一起加油吧!
今天就讲到这里了,拜拜.

在这里插入图片描述

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

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

相关文章

安防监控/视频集中存储/云存储平台EasyCVR v3.3增加首页告警类型

安防监控/视频集中存储/云存储EasyCVR视频汇聚平台&#xff0c;可支持海量视频的轻量化接入与汇聚管理。平台能提供视频存储磁盘阵列、视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联、H.265自动转码等…

湘潭大学 湘大 XTU OJ 1055 整数分类 题解(非常详细)

链接 整数分类 题目 Description 按照下面方法对整数x进行分类&#xff1a;如果x是一个个位数&#xff0c;则x属于x类&#xff1b;否则将x的各位上的数码累加&#xff0c;得到一个新的x&#xff0c;依次迭代&#xff0c;可以得到x的所属类。比如说24&#xff0c;246&#…

Nginx的介绍

本资料转载于传智教育-解锁你的IT职业薪未来&#xff0c;仅用于学习和讨论&#xff0c;如有侵权请联系 视频地址&#xff1a;04-Nginx的优点_哔哩哔哩_bilibili 资源文档&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1RlFl92FdxRUqc858JSxPSQ 提取码&#xff1a;12…

【Vue】全家桶之Axios

文章目录 概述axios特点安装关于 ajax、fetch、axiosAxios APIAxios 实例请求配置响应结构默认配置拦截器错误处理取消请求取消请求请求体编码 概述 Axios是基于promise的网络请求库&#xff0c;可以在nodejs和浏览器中运行&#xff0c;是isomorphic的&#xff0c;意思就是同一…

【仿写tomcat】四、解析http请求信息,响应给前端,HttpServletRequest、HttpServletResponse的简单实现

思考 在解析请求之前我们要思考一个问题&#xff0c;我们解析的是其中的哪些内容&#xff1f; 对于最基本的实现&#xff0c;当然是请求类型&#xff0c;请求的url以及请求参数&#xff0c;我们可以根据请求的类型作出对应的处理&#xff0c;通过url在我们的mapstore中找到se…

使用struct解析通达信本地Lday日线数据

★★★★★博文原创不易&#xff0c;我的博文不需要打赏&#xff0c;也不需要知识付费&#xff0c;可以白嫖学习编程小技巧&#xff0c;喜欢的老铁可以多多帮忙点赞&#xff0c;小红牛在此表示感谢。★★★★★ 在Python中&#xff0c;struct模块提供了二进制数据的打包和解包…

Java 项目日志实例:Log4j2

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ Apache Log4j 2 是对 Log4j 的升级&#xff0c;与其前身 Log4j 1.x 相比有了显着的改进&#xff0c;并提供了许多 Logback 可用的改进&#xff0c;同时支持 JCL 以及 SLF4J…

毫米波雷达成像论文阅读笔记: IEEE TPAMI 2023 | CoIR: Compressive Implicit Radar

原始笔记链接&#xff1a;https://mp.weixin.qq.com/s?__bizMzg4MjgxMjgyMg&mid2247486680&idx1&snedf41d4f95395d7294bc958ea68d3a68&chksmcf51be21f826373790bc6d79bcea6eb2cb3d09bb1860bba0af0fd5e60c448ca006976503e460#rd ↑ \uparrow ↑点击上述链接即…

前端开发,怎么解决浏览器兼容性问题? - 易智编译EaseEditing

解决浏览器兼容性问题是前端开发中常见的挑战之一。不同的浏览器可能对网页元素的渲染和功能支持有所不同&#xff0c;因此需要采取一些策略来确保您的网页在不同浏览器上都能正常运行和呈现。以下是一些解决浏览器兼容性问题的方法和策略&#xff1a; 使用CSS Reset&#xff…

Nuxt3_1_路由+页面+组件+资源+样式 使用及实例

1、 简介 1.1 开发必备 node版本 v16.10.0 我使用的是16.14.0编辑器推荐使用Volar Extension 的VS code插件Terminal 运行nuxt指令 1.2 环境搭建 安装项目&#xff1a; npx nuxilatest init [first_nuxt3]进入项目目录&#xff1a; cd [first_nuxt3]安装依赖&#xff1a;n…

Blazor前后端框架Known-V1.2.13

V1.2.13 Known是基于C#和Blazor开发的前后端分离快速开发框架&#xff0c;开箱即用&#xff0c;跨平台&#xff0c;一处代码&#xff0c;多处运行。 Gitee&#xff1a; https://gitee.com/known/KnownGithub&#xff1a;https://github.com/known/Known 概述 基于C#和Blazo…

探索Perfetto:开源性能追踪工具的未来之光

探索Perfetto&#xff1a;开源性能追踪工具的未来之光 1. 引言 A. 介绍Perfetto的背景和作用 随着移动应用、桌面软件和嵌入式系统的不断发展&#xff0c;软件性能优化变得愈发重要。在这个背景下&#xff0c;Perfetto作为一款开源性能追踪工具&#xff0c;日益引起了开发者…

BC108 矩阵交换

描述 KiKi有一个矩阵&#xff0c;他想知道经过k次行变换或列变换后得到的矩阵。请编程帮他解答。 输入描述 第一行包含两个整数n和m&#xff0c;表示一个矩阵包含n行m列&#xff0c;用空格分隔。 (1≤n≤10,1≤m≤10) 从2到n1行&#xff0c;每行输入m个整数&#xff08;范围-…

java云智慧工地管理平台系统源码

智慧工地将“互联网”的理念和技术引入建筑工地&#xff0c;从施工现场源头抓起&#xff0c;最大程度地收集人员、安全、环境、材料等关键业务数据&#xff0c;依托物联网、互联网&#xff0c;建立云端大数据管理平台&#xff0c;形成“端云大数据”的业务体系和新的管理模式&a…

【CSS动画02--卡片旋转3D】

CSS动画02--卡片旋转3D 介绍代码HTMLCSS css动画02--旋转卡片3D 介绍 当鼠标移动到中间的卡片上会有随着中间的Y轴进行360的旋转&#xff0c;以下是几张图片的介绍&#xff0c;上面是鄙人自己录得一个供大家参考的小视频&#x1f92d; 代码 HTML <!DOCTYPE html>…

BERT、ERNIE、Grover、XLNet、GPT、MASS、UniLM、ELECTRA、RoBERTa、T5、C4

BERT、ERNIE、Grover、XLNet、GPT、MASS、UniLM、ELECTRA、RoBERTa、T5、C4 ELMOBERTERNIE![在这里插入图片描述](https://img-blog.csdnimg.cn/274e31d0f8274c748d05abe2ec65fc73.png)GroverXLNetGPTMASSUniLMELECTRARoBERTaT5C4ELMO BERT

chatGPT-对话爱因斯坦

引言 阿尔伯特爱因斯坦&#xff08; 1879年 3 月 14 日 – 1955 年 4 月 18 日&#xff09;是一位出生于德国的理论物理学家&#xff0c;被广泛认为成为有史以来最伟大、最有影响力的科学家之一。他以发展相对论而闻名&#xff0c;他还对量子力学做出了重要贡献&#xff0c;因…

rfc7234之http缓存

缓存概念 缓存处理请求步骤 缓存如果查询到某个请求已经有缓存&#xff0c;那么需要进一步检查该资源的新鲜度&#xff0c;根据新鲜度和请求中的字段综合评估是否要去服务端拉取新鲜的资源。 注意&#xff1a; 创建响应时候要注意版本匹配&#xff0c;如果服务器响应和客户端…

漏洞指北-VulFocus靶场专栏-中级01

漏洞指北-VulFocus靶场专栏-中级01 中级001 &#x1f338;dcrcms 文件上传 &#xff08;CNVD-2020-27175)&#x1f338;step1&#xff1a;输入账号 密码burp suite 拦截 修改类型为 jpeg 中级002 &#x1f338;thinkphp3.2.x 代码执行&#x1f338;step1&#xff1a;burpsuite …

【ARM】Day6 cotex-A7核UART总线实验

cotex-A7核UART总线实验 1. 键盘输入一个字符‘a’&#xff0c;串口工具显示‘b’ 2. 键盘输入一个字符串"nihao"&#xff0c;串口工具显示“nihao” uart.h #ifndef __UART4_H__ #define __UART4_H__#include "stm32mp1xx_rcc.h" #include "stm3…