C++之函数模板

C++中的函数模板 之前我们知道的交换两个变量的方法有宏定义、函数,这两种方式都能实现两个变量的交换,但是各有各的优缺点 宏定义: - 优点:代码复用,适合所有的类型 - 缺点:缺少类型检查,宏在预处理阶段就被替换掉,编译器并不知道宏的存在 函数: - 优点:真正的函数调用,编译器对类型进行检查 - 缺点:类型不同需要重复定义函数,代码无法复用 上边两种方式... 阅读详情

之前我们知道的交换两个变量的方法有宏定义、函数,这两种方式都能实现两个变量的交换,但是各有各的优缺点
    宏定义:
    - 优点:代码复用,适合所有的类型
    - 缺点:缺少类型检查,宏在预处理阶段就被替换掉,编译器并不知道宏的存在

    函数:
    - 优点:真正的函数调用,编译器对类型进行检查
    - 缺点:类型不同需要重复定义函数,代码无法复用

上边两种方式都各有利弊,但是在C++中,存在泛型编程的概念:即不考虑具体数据类型的编程方式(如下)

C++中的泛型编程有函数模板与类模板,这章我们先来了解函数模板
    函数模板是一种特殊的函数,可以使用不同的类型进行调用,对于功能相同的函数,不需要重复编写代码,并且函数模板与普通函数看起来很类似,区别就是类型可以被参数化

    函数模板通过template与typename两个关键字来定义,class也可以声明泛指类型,如下


以上内容来自:https://blog.youkuaiyun.com/lms1008611/article/details/81985815

下面是一些函数模板的实现:

#include<iostream>
using namespace std;

template <typename T>//声明即将定义一个模板了
void my_swap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

int main()
{
	double i=1.025, j=1.075;
	int m = 1, n = 2;
	//编译器会推断T的数据类型
	my_swap(i, j);
	//显式指定类型,指定T的类型
	my_swap<double>(i, j);
	cout << "i=" << i << endl;
	cout << "j=" << j << endl;
	
	//第二次套用模板
	my_swap(m, n);
	//显式指定类型,指定T的类型
	my_swap<int>(m, n);
	cout << "m=" << m << endl;
	cout << "n=" << n << endl;

	return 0;
	system("pause");
}

注意事项:1.你要能让编译器判断出来你T的类型,不能出现二义性,例如:

my_swap(i, n);

2.不能出现模糊定义的概念,模板必须要确定出T的数据类型,即使你在整个模板函数中没有用到T,你又不显式的指定T的数据类型,那就废了,编译器也不会自动搞明白你的T的类型,程序就会报错。

Tips:使用模板时必须确定出通用数据类型T,并且能够推导出一致的类型。

给出一个算例:

案例描述:

* 利用函数模板封装一个排序的函数,可以对**不同数据类型数组**进行排序

* 排序规则从小到大,排序算法为**选择排序**

* 分别利用**char数组**和**int数组**进行测试

#include<iostream>
using namespace std;

template <typename T>//声明即将定义一个模板了
void my_swap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

template<typename T>
void my_sort(T arry[],const int& length) {//形参数组名,共同拥有一段数组内存空间
	//选择排序法
	for (int i = 0; i < length; i++)
	{
		int min=i;
		for (int j = i + 1; j < length; j++)
		{
			if (arry[min] > arry[j])
				min = j;
		}
		if (min != i)
			my_swap(arry[min], arry[i]);
	}
}

template<typename T>
void my_print(T arry[],const int& length)
{
	for (int i = 0; i < length; i++)
	{
		cout << arry[i] << "\t";
	}
	cout << endl;
}

int main()
{
	char Arry[] = "asdfghjkl";
	int length = sizeof(Arry) / sizeof(char);//不能在模板里边去计算,容易出问题。
	//原因在于sizeof不是函数,而是一个运算符,由编译器来计算的,而不是运行的时候计算的,Arry接收的时候
	//用指针接收,并不知道这个数组的长度,因此会出错
	//所以说,在传数组的时候,往往还是要传入一个数组元素的个数这个参数
	my_sort(Arry,length);//传实参数组的首地址
	my_print(Arry,length);

	int A[] = {5,1,2,3,5,7,8,9,4,6};
	int length1 = sizeof(A) / sizeof(int);
	my_sort(A, length1);//传实参数组的首地址
	my_print(A, length1);

	return 0;
	system("pause");

普通模板与函数模板的区别

#include<iostream>
using namespace std;

template<typename T>
T my_swap(T a, T b)
{
	return(a + b);
}

int main()
{
	char a = 'a'; 
	int b = 2;
	int result = my_swap<int>(a, b);//隐式类型转换,前提是我显式的指定了T的类型(形参不要用引用)
	//如果不指定int,就不可以进行隐式类型转化。如何进行类型转化就是普通函数和函数模板的区别
	//普通函数自动就可以进行类型转换
	return 0;
	system("pause");
}

函数模板和普通函数的调用规则

1. 如果函数模板和普通函数都可以实现,优先调用普通函数

2. 可以通过空模板参数列表来强制调用函数模板

3. 函数模板也可以发生重载

4. 如果函数模板可以产生更好的匹配,优先调用函数模板

#include<iostream>
using namespace std;

void fun(int a, int b)
{
	cout << "普通函数" << endl;
}

template <typename T>
void fun(T a, T b)
{
	cout << "模板函数" << endl;
}

int main()
{
	int a = 0, b = 5;
	fun(a, b);//调普通函数或者模板函数其实都一样,这种情况下,优先调用普通函数
	fun<>(a, b);//当使用空模板的时候,此时会优先调用模板函数
	fun<int>(a, b);//同上,也调用模板函数
	
	char m = 'a';
	char n = 'b';
	fun(m, n);//编译器偷懒,认为我调用模板函数不存在类型转换,所以优先调用模板函数
	fun(a, m);//编译器优先普通函数,因为是自动类型推导,编译器认为不可发生隐式类型转换

	return 0;
	system("pause");
}

既然提供了函数模板,最好就不要提供重名的普通函数,否则容易出现二义性。

 模板函数在自定义数据类型下的处理办法

这也是模板函数的缺点,对于识别出来T是内置的数据类型,直接进行关系运算符进行运算,如果识别出来的T不是内置的数据类型,而是我自定义的比如Person数据类型,那么进行关系运算符进行运算的时候,就会出问题,那个时候就还要进行运算符重载或者再提供一个Person的重载版本,当识别出来T是Person时候,走下面的专属于Person类的代码,具体格式见下面最后一段代码:

#include<iostream>
#include<string>
using namespace std;

class Person {
public:
	Person(const string& s1, const int& age1):name(s1),age(age){}
	bool operator==(Person & p2); 
	string name;
	int age;

};
bool Person::operator==(Person & p2)
{
	if (this->age == p2.age)
		return true;
	else
		return false;
}

template <typename T>
bool compare(T& m1, T& m2)
{
	if (m1 == m2) 
		return true;
	else
		return false;
}
int main()
{
	int a = 0, b = 0;
	cout << boolalpha <<compare(a, b) << endl;//内置的数据类型进行等号判断,OK,可以
	Person p1("张三", 20), p2("李四", 20);
	cout << boolalpha << compare(p1, p2) << endl;//自定义的数据类型就不可以 了,因为在16行判断不出来p1和p2是否相等
	//解决办法1.是运算符重载2.是模板重载
	
	return 0;
	system("pause");
}

上面是利用运算符重载,下面是模板重载的方法

#include<iostream>
#include<string>
using namespace std;

class Person {
public:
	Person(const string& s1, const int& age1):name(s1),age(age){}
	string name;
	int age;

};

template <typename T>
bool compare(T& m1, T& m2)
{
	if (m1 == m2) 
		return true;
	else
		return false;
}
template<> bool compare(Person& m1, Person& m2)
{
	if (m1.age==m2.age)
	{
		return true;
	}
	else
	{
		return false;
	}
}

int main()
{
	int a = 0, b = 0;
	cout << boolalpha <<compare(a, b) << endl;//内置的数据类型进行等号判断,OK,可以
	Person p1("张三", 20), p2("李四", 20);
	cout << boolalpha << compare(p1, p2) << endl;//自定义的数据类型就不可以 了,因为在16行判断不出来p1和p2是否相等
	//解决办法1.是运算符重载2.是模板重载
	
	return 0;
	system("pause");
}
函数模板与宏定义 函数模板与宏定义。代码复用的不同方式的定义,包含了用函数模板实现代码复用,用宏定义展开为函数的定义与使用。 立即下载

相关推荐

Python爬虫实战:避开巨潮资讯网反爬,稳定获取上市公司年报PDF下载地址

本文详细介绍了如何使用Python和Selenium突破巨潮资讯网的动态加载限制,稳定获取上市公司年报PDF下载地址。通过模拟真实用户操作、智能等待策略和反反爬虫技巧,帮助开发者高效爬取财经数据,适用于股票代码查询和年报分析等场景。

weixin_29065659的博客 1667

函数模板template <typename T>

本文实现了一个通用的快速排序函数模板,可以对任意数据类型进行排序。通过模板函数kuaipai()实现了快速排序算法,其中jizhu()函数用于确定基准值位置,change()完成元素交换。程序测试了四种数据类型的排序:整型数组、浮点型数组、字符数组和字符串数组,均能正确输出排序结果。该实现展示了模板编程在多数据类型处理中的优势,通过类型参数T实现了算法复用,避免了为每种数据类型重写排序代码的冗余。

2301_77212325的博客 186

玩转肺癌目标检测数据集Lung-PET-CT-Dx ——①从TCIA获取影像数据集

该目标检测公共数据集源自 The Cancer Imaging Archive(TCIA),是肿瘤研究方面的著名的医学影像公开数据库。 数据以 DICOM 格式存储,由肺癌受试者的 CT 和 PET-CT DICOM 图像组成。

takedachia的博客 1万+

c++ 宏和模板

对单一模板提供的一个特殊实例,它将一个或多个模板参数绑定到特定的类型或值上。

南风知我意 1163

Simulink Test Sequence实战:5步搞定复杂逻辑测试(附Excel模板)

本文详细介绍了如何利用Simulink Test Sequence模块高效完成复杂逻辑测试。通过对比传统Excel方法的不足,阐述了Test Sequence以流程图和自然语言描述测试场景的优势,并提供了从环境搭建、逻辑构建到与Test Manager集成、利用Excel模板进行数据驱动的完整5步实战指南,帮助工程师将复杂的状态机或逻辑流测试从繁琐的‘体力活’转变为高效的‘技术活’。

snow3的博客 251

FOC项目知识点总结三 | 完全搞懂 Clarke 与 Park 变换(附动图,仿真文件以及详细讲解数学推导过程)

本文目的,最终可以完整推算两种变换 Clarke 变换 首先先看我们需要用到的两种坐标系 1. 自然坐标系 abcabcabc 我们知道,通过三相逆变电路,我们可以画出一个自然坐标系 abcabcabc ,即三相电压的坐标系,通入的电流在这三轴坐标系中变化: 将三个矢量相加合并在一起就如下图所展现: 使用三个坐标轴来表示十分的麻烦与不直观,因为其是非正交的,于是乎我们想要将其转化成使用两个正交的坐标轴来表示,于是乎便有了 Clarke变换。 Clarke 变换的作用: 将基于三轴二维的定子静止坐标系的各

Wilson Huang的博客 3万+

c++ 常见宏、模板用法【1】

记录几个常见的好用的宏和模板编程技巧的示例,它们可以提高代码的可读性、可维护性和灵活性,为开发人员提供了更多的选择和工具来处理复杂的编程问题。

hanhan的博客 1076

当AI换脸遇上内容审核:Facefusion NSFW检测的技术伦理与用户自主权之争

本文探讨了Facefusion开源AI换脸工具中NSFW检测机制的技术伦理困境与用户自主权之争。分析了其多层次防御机制的技术实现与社区规避方法,揭示了开源软件在安全与自由之间的平衡难题,并提出了分层权限设计等社区实践方案。

weixin_29165725的博客 687

【C++】函数模板(泛化,部分特化,完全特化)和模板函数

宏定义:在预编译期,进行简单的宏替换优点:代码复用性强缺点:缺少类型检查函数模板:用于泛型编程,(不考虑数据类型进行编程的方式)函数模板通常用:template声明开始进行泛型编程。typename用于声明泛指类型主要作用:提高代码的通用性。

weixin_52958292的博客 567

APM 飞行模式切换--源码详解

APM飞控中有很多种方式可以改变飞行模式。其中最常见的为遥控器切换和地面站切换两种方式。 下面以遥控器切换为例详解飞行模式切换逻辑。 APM遥控器切换飞行模式的源代码在RC_Channel.cpp文件中的RC_Channel_Copter::do_aux_function_change_mode()函数中。 const bool success = copter.set_mode()调用Copter::set_mode()函数,在set_mode()函数中调用mode_fro...

qq_30623591的博客 2440

智能车浅谈——手把手让车跑起来(电磁篇)

手把手让你的电磁车上路。

qq_41954556的博客 7万+

C++——函数模板

函数模板的定义 函数模板定义的一般形式如下: template<类型形式参数表> 返回类型 函数名(形式参数表) { //函数体 } template为关键字,表示定义一个模板,尖括号<>表示模板参数,模板参数主要有两种,一种是模板类型参数,另一种是模板非类型参数。上述代码中定义的模板使用的是模板类型参数,模板类型参数使用关键字class或typedef开始,其后是一个用户定义的合法标识符。模板非类型参数与普通参数定义相同,通常为一个常数。 可以将声明函数模板分成templ

weixin_50464560的博客 688

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合ollama无限token实现7*24小时工作(附配置)

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合 ollama 无限token实现7*24小时工作,以及部署安装需要的 skills 完成复杂的工作任务(附完整可以运行的配置文件)。 很多人已经会配置安装 openclaw 了 ,但是 安装完成之后真正让电脑自动运行起来的很好,完成出色工作的更少,最常见的就是聊聊天,或者执行一些简单的命令,理解要让电脑自动化工作,openclaw、skills、大模型这三样。

代码讲故事 2963

C++函数模板

模板是一个通用框架,是C++泛型编程思想的主要体现。C++提供了函数模板和类模板两种模板机制,本文介绍的是函数模板相关的知识。

weixin_44205961的博客 5918

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C++模板、类模板、函数模板详解都在这里了

C++模板、类模板、函数模板详解一、引言二、函数模板1、定义2、调用3、多个虚类型三、类模板1、定义2、调用四、类的函数模板五、类作为数据类型传入六、类模板与继承七、类模板与友元 一、引言 在写排序算法时,如果要写一个交换两个数据的函数,由于基本数据类型有int、float、double等等类型,所以针对每种数据类型可能我们要写很多swap函数,这些函数除了传入的数据类型不同,函数体结构大致相同。...

hsxyfzh的博客 1万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C++函数模板及实现原理

C++为我们提供了函数模板机制。所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。 凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。     为什么要有函数模板     下面,我们就通过一个例子来说

常敲代码手不抖 2万+

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

cpp中的函数模板

之前我们讲了函数重载,对一个不同参数类型的函数作出了不同的行为,但是其实有一个更加高效的方式,那就是函数模板,也叫泛型编程。或者模板元编程。下面是一个交换两个元素的例子我们只需要在调用时指定类型就可以我们也可以指定两种类型,下面的程序没有什么实际意义,就是为了展示一下

Lyajpunov的博客 1434

C++函数模板的详细讲解【函数模板的概念、用法及其模板函数的概念知识】

目录前言C++函数模板的使用函数模板语法1.模板说明2.函数定义3.函数模板调用模板函数函数模板和函数重载 前言 C++提供了模板(template)编程的概念。所谓模板,实际上是建立一个通用函数或类,其类内部的类型和函数的形参类型不具体指定,用一个虚拟的类型来代表。这种通用的方式称为模板。模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。 C++函数模板的使用 为什么要有函数模板 例如,在一个项目中,有个项目需求是能够实现多个函数用来返回两个数的最大值,要求能支持char类型、int

m0_53636439的博客 5万+

C++ 函数模板基础

C++ 函数模板基础

英雄哪里出来 5074

C++编程——函数模板

文章目录1 函数模板语法2 函数模板注意事项3 函模模板案例4 普通函数与函数模板的区别5 普通函数与函数模板的调用规则6 模板的局限性 模板就是建立通用的模具,大大提高复用性 模板的特点: 模板不介意直接使用,它只是一个框架 模板的通用并不是万能的 C++另一种编程思想称为泛型编程,主要利用的技术就是模板 C++提供两种模板机制:函数模板和类模板 本文介绍的是函数模型的知识 1 函数模板语法 函数模板作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表 语法: te

professor_tao的博客 6176

Cpp--C++中函数模板的用法详细解析

C++中的模板可分为函数模板和类模板,而把函数模板的具体化称为模板函数,把类模板的具体化成为模板类。下面让我们分别看看什么是函数模板和类模板吧 1.什么是模板 假设现在我们完成这样的函数,给定两个数x和y求式子x^2 + y^2 + x * y的值 .考虑到x和y可能是 int , float 或者double类型,那么我们就要完成三个函数: int fun(

samkieth 806

C++ 函数模板

函数模板:通过模板参数定义通用函数,编译器根据实际参数类型生成具体函数实现。decltype:用于在编译时查询表达式的数据类型,不计算表达式的值。函数后置返回类型:允许将返回类型放在函数参数列表之后,适用于复杂类型推导。注意事项:包括模板参数的匹配、隐式类型转换、多个参数、模板重载等。函数模板的具体化:允许为特定类型提供函数模板的特定实现。通过这些概念和用法,你可以编写更灵活和强大的模板代码,处理各种复杂的类型和表达式。

qq_50373827的博客 1445
上一篇: C++之类继承和多态(虚函数、构造函数,析构函数)
下一篇: C++之类模板
Worthwhile_HUST
博客等级 码龄5年 53粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值