【c++】模板1—函数模板
文章目录
- 函数模板语法
- 函数模板注意事项
- 案例—数组选择排序
- 普通函数和函数模板的区别
- 普通函数和函数模板调用规则
- 模板的局限性
函数模板语法
函数模板作用:
建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template<typename T>
函数声明或定义
解释:
template—声明创建模板
typename—表明其后面的符号是一种数据类型,可以用class代替
T—通用的数据类型,名称可以替换,通常为大写字母
#include<iostream>
using namespace std;//交换两个整型函数
void swapint(int& a, int& b)
{int temp = a;a = b;b = temp;
}
//交换两个浮点型函数
void swapdouble(double& a, double& b)
{double temp = a;a = b;b = temp;
}//函数模板
template<typename T>//声明一个模板,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用数据类型
void myswap(T& a, T& b)
{T temp = a;a = b;b = temp;
}void test()
{int a = 10;int b = 20;double c = 1.11;double d = 2.22;//两种方式使用函数模板//1、自动类型推导myswap(a, b);cout << "a = " << a << endl;cout << "b = " << b << endl;//2、显示指定类型myswap<double>(c, d);cout << "c = " << c << endl;cout << "d = " << d << endl;
}int main()
{test();system("pause");return 0;
}
总结:
1、函数模板利用关键字template;
2、使用函数模板有两种方式:自动类型推导、显示指定类型;
3、模板的目的是为了提高复用性,将类型参数化。
函数模板注意事项
1、自动类型推导,必须推导出一致的数据类型T,才可以使用;
2、模板必须要确定出T的数据类型,才可以使用。
#include<iostream>
using namespace std;//函数模板
//template<typename T>
template<class T>//typename可以替换成class
void myswap(T& a, T& b)
{T temp = a;a = b;b = temp;
}void test01()
{int a = 10;int b = 20;char c = 'c';//1、自动类型推导,必须推导出一致的数据类型T才可以使用myswap(a, b);//myswap(a, c);//错误!推导不出一致的T类型cout << "a = " << a << endl;cout << "b = " << b << endl;
}//2、模板必须要确定出T的数据类型,才可以使用
template<class T>
void func()
{cout << "func调用" << endl;
}void test02()
{//func();//错误!无法确定出T的数据类型func<int>();//函数用不上数据类型,可以随便写一个数据类型
}int main()
{test01();test02();system("pause");return 0;
}
案例—数组选择排序
利用函数模板封装一个排序的函数,可以对不同数据类型数组进行排序。
排序规则从大到小,排序算法为选择排序。
分别利用char数组和int数组进行测试。
#include<iostream>
using namespace std;//实现通用 对数组进行排序的函数
//规则 从小到大
//算法 选择排序
//测试 char数组、int数组//交换函数模板
template<class T>
void myswap(T& a, T& b)
{T temp = a;a = b;b = temp;
}//排序算法
template<class T>
void mysort(T arr[], int len)
{for (int i = 0; i < len; i++){int min = i;//认定最大值的下标for (int j = i + 1; j < len; j++){if (arr[min] > arr[j]){min = j;//更新最大值下标}}if (min != i){//交换max和i元素myswap(arr[min], arr[i]);}}
}//打印数组模板
template<class T>
void printarray(T arr[], int len)
{for (int i = 0; i < len; i++){cout << arr[i] << " ";}cout << endl;
}void test01()
{//测试char数组char arr1[] = "adebcgf";int num = sizeof(arr1) / sizeof(char);mysort(arr1, num);printarray(arr1, num);
}void test02()
{//测试int数组int arr2[] = { 1,8,2,5,9,3,4,7,6 };int num = sizeof(arr2) / sizeof(int);mysort(arr2, num);printarray(arr2, num);
}int main()
{test01();test02();system("pause");return 0;
}
普通函数和函数模板的区别
1、普通函数调用时可以发生自动类型转换(隐式类型转换);
2、函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换;
3、函数模板调用时,如果利用显示指定类型的方式,可以发生隐式类型转换。
#include<iostream>
using namespace std;//普通函数
int add1(int a, int b)
{return a + b;
}//函数模板
template<class T>
T add2(T a, T b)
{return a + b;
}void test()
{int a = 10;int b = 20;char c = 'c';//ASCII码:a - 97,c - 99double d = 1.11;cout << add1(a, c) << endl;//自动类型推导,不会发生隐式类型转换//cout << add2(a, c) << endl;//错误!//显示指定类型,可以发生隐式类型转换cout << add2<int>(a, c) << endl;cout << add2<int>(a, d) << endl;
}int main()
{test();system("pause");return 0;
}
函数模板调用时:
1、使用自动类型推导的方式,必须推导出一致的数据类型T,才可以使用;
2、使用显示指定类型的方式,可以发生隐式类型转换,即使数据类型不一致,也可以使用。
普通函数和函数模板调用规则
调用规则如下:
1、如果函数模板和普通函数都可以调用,优先调用普通函数;
2、可以通过空模板参数列表强制调用函数模板;
3、函数模板也可以发生重载;
4、如果函数模板可以产生更好的匹配,优先调用函数模板。
#include<iostream>
using namespace std;void print(int a, int b)
{cout << "调用普通函数" << endl;
}template<class T>
void print(T a, T b)
{cout << "调用函数模板" << endl;
}template<class T>
void print(T a, T b, T c)
{cout << "调用重载的函数模板" << endl;
}void test()
{int a = 10;int b = 20;//1、如果函数模板和普通函数都可以调用,优先调用普通函数print(a, b);//2、可以通过空模板参数列表强制调用函数模板print<>(a, b);//3、函数模板也可以发生重载print(a, b, 100);//4、如果函数模板可以产生更好的匹配,优先调用函数模板char c = 'c';char d = 'd';print(c, d);
}int main()
{test();system("pause");return 0;
}输出:
调用普通函数
调用函数模板
调用重载的函数模板
调用函数模板
模板的局限性
模板的通用性并不是万能的,有些特定数据类型,需要用具体化方式做特殊实现。
#include<iostream>
using namespace std;
#include<string>class person
{
public:person(string name, int age){this->m_name = name;this->m_age = age;}string m_name;int m_age;
};//对比两个数据是否相等
template<class T>
bool compare(T& a, T& b)
{if (a == b){return true;}else{return false;}
}//利用具体化person的版本实现代码,具体化优先调用
template<> bool compare(person& p1, person& p2)
{if (p1.m_name == p2.m_name && p1.m_age == p2.m_age){return true;}else{return false;}
}void test1()
{int a = 10;int b = 20;bool ret = compare(a, b);if (ret){cout << "a == b" << endl;}else{cout << "a != b" << endl;}
}void test2()
{person p1("张三", 18);person p2("张三", 18);bool ret = compare(p1, p2);if (ret){cout << "a == b" << endl;}else{cout << "a != b" << endl;}
}int main()
{test1();test2();system("pause");return 0;
}
总结:
1、利用具体化的模板,可以解决自定义类型的通用化;
2、学习模板并不是为了写模板,而是在STL能够运用系统提供的模板。
相关文章:
【c++】模板1—函数模板
文章目录函数模板语法函数模板注意事项案例—数组选择排序普通函数和函数模板的区别普通函数和函数模板调用规则模板的局限性函数模板语法 函数模板作用: 建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表…...
windows10 wsl子系统固定ip启动分配网卡法
WSL设置添加固定IP 在Win端添加一个固定IP 192.168.50.99 用于X-Server界面显示.在WSL端添加一个固定IP 192.168.50.16 用于和Win端通讯 在win端创建批处理文件 创建一个批处理文件 我的文件位置是D:\powershell\static_ip.bat 向vEthernet (WSL)网卡添加一个IP 192.168.50.…...
ARM+Linux日常开发笔记
ARMLinux开发命令 文章目录ARMLinux开发命令一、虚拟机1.ssh服务项目2.文件相关3.系统相关4. 虚拟机清理内存二、ARM核板1.设备重启三、调试1. 应该调试一、虚拟机 1.ssh服务项目 启动ssh服务 sudo /etc/init.d/ssh restart2.文件相关 查看文件大小显示kb ll -h 查看目录文件…...
在线文档技术-编辑器篇
这是在线文档技术的第二篇文章,本文将对目前市面上所有的主流编辑器和在线文档进行一次深入的剖析和研究,从而使大家对在线文档技术有更深入的了解,也让更多人能够参与其开发与设计中来。 注意:出于对主流文档产品的尊重…...
top -p pid为什么超过100%
CPU:Cores, and Hyper-Threading 超线程(Hyper-Threading ) 超线程是Intel最早提出一项技术,最早出现在2002年的Pentium4上。单个采用超线程的CPU对于操作系统来说就像有两个逻辑CPU,为此P4处理器需要多加入一个Logic…...
#高光谱图像分类#:分类的方法有哪些?
高光谱图像分类方法可以根据分类粒度的不同分为基于像素的分类和基于对象的分类 高光谱图像分类方法可以根据分类粒度的不同分为基于像素的分类和基于对象的分类。 基于像素的分类:这种分类方法是针对每个像素进行分类,将像素的光谱信息作为输入特征&am…...
观察者模式
观察者模式常常用于以下场景:事件驱动系统:当事件发生时,通知所有对该事件感兴趣的观察者。发布/订阅模型:一个主题(发布者)可以有多个订阅者(观察者),当主题发生改变时&…...
前端组件库自定义主题切换探索-03-webpack-theme-color-replacer webpack 同时替换多个颜色改造
接上一篇《前端组件库自定义主题切换探索-02-webpack-theme-color-replacer webpack 的实现逻辑和原理-02》 这篇我们来开始改造,让这个插件最终能达到我们的目的: 首先修改plugin.config.js。 插件首先要在vue.config.js引用注册,因此先对…...
Redis高级-主从复制相关操作
2.1 主从复制简介 2.1.1 高可用 首先我们要理解互联网应用因为其独有的特性我们演化出的三高架构 高并发 应用要提供某一业务要能支持很多客户端同时访问的能力,我们称为并发,高并发意思就很明确了 高性能 性能带给我们最直观的感受就是:速…...
SPI总线设备驱动模型
SPI总线设备驱动模型 文章目录SPI总线设备驱动模型参考资料:一、平台总线设备驱动模型二、 数据结构2.1 SPI控制器数据结构2.2 SPI设备数据结构2.3 SPI设备驱动三、 SPI驱动框架3.1 SPI控制器驱动程序3.2 SPI设备驱动程序致谢参考资料: 内核头文件&…...
开发同事辞职,接手到垃圾代码怎么办?
小王新加入了一家公司,这家公司有点年头,所以连屎山都是发酵过的,味道很冲。和大多数时运不济的程序员一样,到了这种公司,做的大多数工作,就是修补这些祖传代码,为其添砖加瓦。每当被折腾的筋疲…...
gRPC简介
grpc简介 grpc介绍可以参考官网。无论是rpc还是grpc,可以这样理解,都知道过去使用的单单体架构,而在2011年5月威尼斯的一个软件架构会议上提出了微服务架构,围绕业务功能进行组织(organized around business capability)…...
《MySQL系列-InnoDB引擎25》表-InnoDB逻辑存储结构
InnoDB逻辑存储结构 从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace)。表空间又由段(segment)、区(extent)、页(page)组成。页在一些文档中有时也称为块(block),InnoDB存储引擎的逻辑存储结构…...
YOLOv8之C2f模块——与YOLOv5的C3模块对比
一、源码对比 YOLOv8完整工程代码下载:ultralytics/ultralytic C2f模块源码在ultralytics/nn/modules.py下,源码如下: class C2f(nn.Module):# CSP Bottleneck with 2 convolutionsdef __init__(self, c1, c2, n1, shortcutFalse, g1, e…...
动态规划实例——换零钱的方法数(C++详解版)
原写了 Java 版本的如何求解换钱的方法数,近期进行了一些细节上的补充,以及部分错误更正,将语言换为了 C 语言。 基础题目 假设你现在拥有不限量的 1 元、5 元、10 元面值纸币,路人甲希望找你换一些零钱,路人甲拿出的…...
linux c
射频驱动 管理硬件设备、分配系统资源 内核由中断服务程序 调度程序 内存管理程序 网络和进程间进程通信程序 linux支持动态加载内核模块 支持多处理smp机制 内核可以抢占preemptive linux系统拥有多个发行版,可能由一个组织 公司和个人发行 VGA兼容或者更…...
第十三章 系统错误消息 - 一般系统错误消息 S - Z
文章目录第十三章 系统错误消息 - 一般系统错误消息 S - Z第十三章 系统错误消息 - 一般系统错误消息 S - Z 错误代码描述<SUBSCRIPT>下标值不合法或Global引用过长。<SWIZZLE FAIL>打开了一个oref,然后试图在另一个无法引用的相关对象中进行搅拌。这可…...
移动web基础
初始缩小:布局视口大于视觉视口 初始放大:布局视口小于视觉视口 布局视口等于视觉视口(这种动作行为叫做理想视口) <meta name"viewport" content"width375" /> <meta name"viewport"…...
MyBatis和MyBatis_Plus有什么区别【面试常考题】
MyBatis和MyBatis_Plus的区别 MyBatis_Plus MyBatis_Plus 是一个 MyBatis 的增强工具,只是在 MyBatis 的基础上增强了却没有做改变,MyBatis-Plus支持所有MyBatis原生的特性,所有引入MyBatis-Plus不会对现有的MyBatis框架产生任何影响。 MyBa…...
华为OD机试用Python实现 -【统一限载货物数最小值】(2023-Q1 新题)
华为OD机试题 华为OD机试300题大纲统一限载货物数最小值题目描述输入描述输出描述说明示例一输入输出说明示例二输入输出说明Python 代码实现算法逻辑华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
window 显示驱动开发-如何查询视频处理功能(三)
D3DDDICAPS_GETPROCAMPRANGE请求类型 UMD 返回指向 DXVADDI_VALUERANGE 结构的指针,该结构包含特定视频流上特定 ProcAmp 控件属性允许的值范围。 Direct3D 运行时在D3DDDIARG_GETCAPS的 pInfo 成员指向的变量中为特定视频流的 ProcAmp 控件属性指定DXVADDI_QUER…...
Neo4j 完全指南:从入门到精通
第1章:Neo4j简介与图数据库基础 1.1 图数据库概述 传统关系型数据库与图数据库的对比图数据库的核心优势图数据库的应用场景 1.2 Neo4j的发展历史 Neo4j的起源与演进Neo4j的版本迭代Neo4j在图数据库领域的地位 1.3 图数据库的基本概念 节点(Node)与关系(Relat…...
