函数模板与类模板初阶

news2024/12/23 18:33:46

如果要写一个交换函数,不同类型的话调用不同的交换函数,如果使用重载的话只能解决函数名相同但是会根据参数类型调用不同的函数。即使这样也依旧要写很多不同类型的swap交换函数

函数重载的交换函数

仔细观察会发现除了类型不同其他的函数结构什么的都一样,都是定义中间变量,然后用它作为过渡交换其他的两个变量。因此可以用C++模版的知识,告诉编译器一个模子,让编译器根据不同类型 利用该模子来生成代码。其实本质上还是写了三个函数,只是模版是让编译器帮你写而已。

通俗点讲就是让编译器往这个模具中填充不同的材料(类型),来获得不同材料的产品(即生成具体的代码)

模板分为两个部分,函数模板和类模板

函数模板

函数模板是函数形式的模板,在编译器编译阶段,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用,需要什么,编译器帮助你实例化你要的函数,比如:当用double类型使用函数模板时,编译器根据传过来参数的类型进行推演,讲实参确定为double类型,然后产生一份专门处理double类型的代码。对于别的类型,比如int它也会直接推演成int类型的函数,本质上还是写了函数,只是编译器自动帮你干了。

函数模板格式

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名 ( 参数列表 ){}

用swap举例子就是

#include<iostream>
using namespace std;

template<typename T>
void swap1(T& a, T& b)
{
	T c = a;
	a = b;
	b = c;
}

int main()
{
	int a = 3; int b = 7;
		swap1(a,b);
		cout << a << endl;
		cout << b << endl;
}

 

但是我为什么写模板swap要写成swap1,这是因为编译器把一些常用的函数已经写成了函数,swap就是其中之一,所以你再写一个swap交换模板就会报错

 函数模板的实例化

 模板参数实例化分为:隐式实例化和显示实例化,隐式实例化就是和上面swap1模板调用一样不告诉编译器要什么类型swap(a,b),让编译器自己根据实参类型去推演。而显式实例化是告诉了编译器要让模板生成什么类型的函数,基本方式为在函数名后的<>中指定模板参数的实际类型

同样依旧是swap1函数显示实例化的样子

如果传的参数是不同的类型的,编译器会怎么去推演呢,比如add模板,我用一个int类型+double类型会怎么样呢

隐式调用模板

从上图可以看出隐式调用模板会直接报错,因为编译器不知道把T推演出int类型还是double类型 

解决办法是把其中一个强制转换成另一个一样的类型,比如把double装换成int类型,但是这样一定会发生精度的丢失

#include<iostream>
using namespace std;

template<typename T>
T add(const T& a, const T& b)
{
	return a + b;
}

int main()
{
	int a = 3; double b = 7.5;
	int ret = add(a, (int)b);//把double类型强制转换成int类型
	cout << ret<< endl;
}

但是为什么这里函数形参为什么都加上const呢,把const删了会依旧找不到add,会报错

这是因为类型转换实际上也会产生临时变量进行过渡,double类型强转int转换过程会丢弃浮点数的小数部分。这意味着,无论小数点后的数字是什么,都会被直接忽略。这个过程被称为截断。截断后的整数部分被赋值给一个 int 类型的临时变量(如果这是显式转换的结果)。这个临时变量是编译器在内部生成的,用于存储转换后的整数值。

因为是临时变量具有常性,int引用实际上引用的是这个临时变量,所以要加const

第二种方法是模板T类型直接用改成两个,一个传int类型,一个传double类型。也就是将template<typename T>改成template<typename T1,typename T2>; 但是究竟传什么类型回来呢,难点在于我并不知道返回的究竟是T1还是T2,所以返回值直接用auto修饰,让编译器自己去推导就可以解决了

#include<iostream>
using namespace std;

template<typename T1, typename T2>
auto add(const T1& a, const T2& b)
{
	return a + b;
}

int main()
{
	int a = 3; double b = 7.5;
	int ret = add(a, (int)b);
	cout << ret<< endl;
}

第三种办法就是显示实例化

 总结一下如果有不同的类型的参数调函数模板,无论怎样都要进行强制类型转换,都会造成精度的丢失

模板参数匹配规则

如果既有普通的函数又有函数模板推导并且普通函数参数和调用的地方实参类型对应的上的话,那么编译器会优先调用普通函数(优先匹配普通函数+参数匹配)

 如果没有普通的函数或者普通的函数参数和实参类型对应不上的话,会去优先匹配参数类型对应的上的函数模板

总结一下就是先普通函数然后模板函数

类模板格式

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

 

// 动态顺序表
// 注意: Vector 不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template < class T >
class Vector
{
public :
Vector ( size_t capacity = 10 )
: _pData ( new T [ capacity ])
, _size ( 0 )
, _capacity ( capacity )
{}
// 使用析构函数演示:在类中声明,在类外定义。
~Vector ();
void PushBack ( const T & data )
void PopBack ()
// ...
size_t Size () { return _size ;}
T & operator []( size_t pos )
{
assert ( pos < _size );
return _pData [ pos ];
}
private :
T * _pData ;
size_t _size ;
size_t _capacity ;
};
// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template < class T >
Vector < T > :: ~Vector ()
{
if ( _pData )
delete [] _pData ;
_size = _capacity = 0 ;
}

通俗点类模板只是使类成员成为模板类型而已,可一个也可以所有都成为模板类型。

 类模板实例化

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

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

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

相关文章

Postman 在 Linux 上的安装指南:简单快速开始使用

本文将介绍如何在 Linux 上安装 Postman 的详细步骤&#xff0c;Postman 支持的 Linux 的发行版包括&#xff1a;Ubuntu 14.04 及更高版本&#xff0c;Fedora 24&#xff0c;Debian 8 及更高版本。下面将介绍其具体的安装方法。 手动安装 Postman 的下载地址&#xff0c;下载…

一、Django 初识

简介 Django 是一个用于构建 Web 应用程序的高级 Python Web 框架。 版本对应 不同版本的django框架是基于特定的不同的python版本开发的&#xff0c;所以不同版本的django框架要正常执行功能只能安装特定的python版本 Django安装 安装 Django # 全局安装 pip install dj…

泰坦尼克号乘客生存情况预测分析2

泰坦尼克号乘客生存情况预测分析1 泰坦尼克号乘客生存情况预测分析2 泰坦尼克号乘客生存情况预测分析3 泰坦尼克号乘客生存情况预测分析总 背景描述 Titanic数据集在数据分析领域是十分经典的数据集&#xff0c;非常适合刚入门的小伙伴进行学习&#xff01; 泰坦尼克号轮船的…

ionic 中对Input输入框、searchbar进行solr检索

一、概述 Ionic 是一个用于开发跨平台应用程序的开源工具&#xff0c;可以使用 Angular、React 或 Vue 等前端框架。要在 Ionic 应用程序中实现实时与 Solr 通信&#xff0c;可以使用 HTTP 客户端&#xff08;如 Angular 的 HttpClient 或 Ionic 的 Native HTTP&#xff09;…

笔记:编写程序,绘制一个展示 2013~2019 财年阿里巴 巴淘宝+天猫平台的 GMV 的柱形图,实现过程如下:

文章目录 前言一、GMV 的柱形图是什么&#xff1f;二、编写代码总结 前言 编写程序。根据实例 2 的要求&#xff0c;绘制一个展示 2013~2019 财年阿里巴 巴淘宝天猫平台的 GMV 的柱形图&#xff0c;实现过程如下&#xff1a; &#xff08;1&#xff09; 导入 matplotlib.pypl…

Linux快速部署大语言模型LLaMa3,Web可视化j交互(Ollama+Open Web UI)

本文在个人博客同步发布&#xff0c;前往阅读 1 介绍 本文将介绍使用开源工具Ollama(60.6k⭐)部署LLaMa大模型&#xff0c;以及使用Open WebUI搭建前端Web交互界面的方法。 我们先来过一遍几个相关的概念&#xff0c;对这块比较熟悉的朋友可跳过。 1.1 大规模语言模型 大规…

从递归角度串联二叉树-图论-动态规划

一、深度理解二叉树的前中后序遍历 二叉树遍历框架如下&#xff1a; void traverse(TreeNode* root) {if (root nullptr) {return;}// 前序位置traverse(root->left);// 中序位置traverse(root->right);// 后序位置 }先不管所谓前中后序&#xff0c;单看 traverse 函数…

keytool,openssl的使用

写在前面 在生成公钥私钥&#xff0c;配置https时经常需要用到keytool&#xff0c;openssl工具&#xff0c;本文就一起看下其是如何使用的。 keytool是jdk自带的工具&#xff0c;不需要额外下载&#xff0c;但openssl需要额外下载 。 1&#xff1a;使用keytool生成jks私钥文件…

Office Word自动编号转文本

原理 使用office自带的宏功能&#xff0c;一键替换 过程 调出word的“开发工具”选项 文件->选项->自定义功能区->选中开发工具->确定 创建宏 开发工具->宏->创建宏 编写宏 在弹出来的框里&#xff0c;替换代码为 Sub num2txt() ActiveDocument.…

ArcGIS批量寻找图层要素中的空洞

空洞指的是图层中被要素包围所形成的没有被要素覆盖的地方&#xff0c;当图层要素数量非常庞大时&#xff0c;寻找这些空洞就不能一个一个的通过目测去寻找了&#xff0c;需要通过使用工具来实现这一目标。 一、【要素转线】工具 利用【要素转线】工具可以将空洞同图层要素处于…

电商技术揭秘三十五:智能风控功能架构浅析

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘二十八&#xff1a;安全与合规性保障 电商技术揭秘二十九&#xff1a;电商法律合规浅析 电商技术揭秘三十&#xff1a;知识产权保…

WEB攻防-PHP特性-CMS审计实例

前置知识&#xff1a;PHP函数缺陷 测试环境&#xff1a;MetInfo CMS 函数缺陷导致的任意文件读取 漏洞URL&#xff1a;/include/thumb.php?dir 漏洞文件位置&#xff1a;MetInfo6.0.0\app\system\include\module\old_thumb.class.php <?phpdefined(IN_MET) or exit(No…

ElasticSearch语句中must,must_not,should 组合关系

前言&#xff1a; 在实际应用中&#xff0c;发现当bool中同时使用must和should 没有达到想要的想过&#xff0c;而是只展示了must中的命中数据&#xff0c;所以打算探究一下bool中 三种逻辑关系的组合。 上述查询语句只展示了must的结果&#xff0c;没有should中的结果&#…

Kafka 3.x.x 入门到精通(06)Kafka进阶

Kafka 3.x.x 入门到精通&#xff08;06&#xff09;——对标尚硅谷Kafka教程 3. Kafka进阶3.1 Controller选举3.2 Broker上线下线3.3 数据偏移量定位3.4 Topic删除3.5 日志清理和压缩3.7 页缓存3.8 零拷贝3.9 顺写日志3.10 Linux集群部署3.10.1 集群规划3.10.2 安装虚拟机(略)3…

MemFire解决方案-物联网数据平台解决方案

方案背景 随着各种通讯、传感技术发展&#xff0c;数据通讯成本的急剧下降&#xff0c;数以万亿计的智能设备&#xff08;智能手环、智能电表、智能手机、各种传感器设备等&#xff09;接入网络&#xff0c;并源源不断的产生海量的实时数据。这些海量数据的价值挖掘&#xff0…

15.Blender Eevee和Cycles渲染引擎对比

初步介绍 Eevee是实时渲染的引擎&#xff0c;会省略一些解算方式&#xff0c;尤其对光线和阴影 Cycles会考虑这些因素&#xff0c;所以会对光线和阴影的表达更加真实&#xff0c;有一个实时光线追踪的功能 Cycles渲染完之后&#xff0c;每移动一次画面&#xff0c;都会重新渲染…

机器学习之Scikit-learn基础教程

Scikit-learn&#xff08;简称sklearn&#xff09;是一个广泛使用的Python机器学习库&#xff0c;它提供了各种算法和工具&#xff0c;用于数据挖掘和数据分析。本教程将介绍sklearn的基本概念和使用方法。 1. 安装Scikit-learn 如果你还没有安装scikit-learn&#xff0c;可以…

设计模式学习笔记 - 开源实战五(下):总结Mybatis中用到的10种设计模式

概述 本章再对 Mybatis 用到的设计模式做一个总结。它用到的设计模式也不少。有些前面章节已经经过了&#xff0c;有些则比较简单。 SqlSessionFactoryBuilder&#xff1a;为什么要用建造者模式来创建 SqlSessionFactory&#xff1f; 在《Mybatis如何权衡易用性、性能和灵活性…

nvm的下载与安装

nvm&#xff08;Node Version Manager&#xff09;是一个用于管理 Node.js 版本的工具&#xff0c;它允许您在同一台计算机上安装和切换不同的 Node.js 版本。 一、下载地址 https://github.com/coreybutler/nvm-windows/releases 二、安装nvm 三、设置环境变量 在命令提示…

python之List列表

1. 高级数据类型 Python中的数据类型可以分为&#xff1a;数字型&#xff08;基本数据类型&#xff09;和非数字型&#xff08;高级数据类型&#xff09; 数字型包含&#xff1a;整型int、浮点型float、布尔型bool、复数型complex 非数字型包含&#xff1a;字符串str、列表l…