IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++函数模板详解 -> 正文阅读

[C++知识库]C++函数模板详解

C++函数模板

在我们对不同数据类型的程序逻辑和操作相同时,使用函数模板会非常的方便,只需要定义单个函数模板。函数模板实际上就是对数据类型进行了参数化。
模板的定义都以template开头,后面跟着尖括号括起来的类型参数,类型参数的参数名可以是typename、也可以是class,他们作用是一致的。

#include <iostream>
using namespace std;

template<typename T>
bool compare(T a, T b)
{
	return a > b;
}

int main()
{
	compare<int>(10, 20);
	compare(10.0, 10.2);
	compare("aaa", "bbb");

	return 0;
}

模板函数调用及实参推演

函数模板调用在函数名后面跟上尖括号,尖括号里传入指定的数据类型,和函数实参,如compare<int>(10, 20);
但是不传入类型实参也可以实现模板函数的调用,如compare(10.0, 10.2);,这是因为函数模板可以进行实参推演,可以根据用户传入实参的类型,推导出实参的类型参数的具体类型。
但这样的代码:compare(10, 10.2);编译是不能通过的。因为函数模板中形参的类型是相同的,但传入的实参类型不同,编译器不知道要用哪个类型来实例化,我们可以通过指定具体类型的模板函数来解决这个问题,如:compare<int>(10, 10.2);compare<double>(10, 10.2);

未指定模板类型时,编译器会优先匹配普通函数,没有匹配的普通函数再去类型推导实例化模板函数。

函数模板实例化

函数模板的实例化是在编译阶段完成的,在函数调用点,编译器会从用户指定的类型,从函数模板实例化一份模板函数代码出来,相同的类型参数只会实例化出一份代码,否则会出现函数重定义。
如上面的代码中,compare<int>(10, 20);实例化的模板函数代码如下:


bool compare<int>(int a, int b)
{
	return a > b;
}

函数模板中花括号中的代码,是不参与编译的。因为传入的类型参数可能是类,也可能是普通的数据类型,比如在 编译a > b;时,因为a和b的类型不确定,编译器不知道要进行的是普通的比较,还是执行对象的operator>,所有函数模板的函数体是不参与编译的。

函数模板特例化

在对compare("aaa", "bbb");实例化模板函数时,实例化出这样的代码:

bool compare<const char*>(const char* a, const char* b)
{
	return a > b;
}

在对const char* 进行 > 比较是没有太大意义的,我们实际想要的是 strcmp(a, b) > 0;,这时模板函数的逻辑和操作已经不能满足我们所有的需求了。
对于某些特定类型来说,以来函数模板默认实例化的模板函数代码,不能满足它的处理逻辑时,我们就需要定义模板的特例化
例如对上面compare函数定义的const char*类型的模板特例化:

template<>
bool compare(const char* a, const char* b)
{
	return strcmp(a, b) > 0;
}

在模板特例化时,应定义为template<>,而不是template<typename T>,否则在模板类型推导时,就会实例化出默认的模板函数。函数模板推导是根据形参列表来推导的,所以如果模板特例化时定义为template<typename T>,而形参列表中没有类型T,就不会进行类型推导了。
在这里插入图片描述

跨文件使用模板的坑

在头文件声明模板,在另一个文件定义,再在另一个文件包含头文件使用时,会发生链接错误。
因为函数模板实例化是在编译阶段完成的,而.cpp文件是单独编译,在定义模板的文件中并没有发生函数调用,也就不会实例化出模板函数,链接时就会发生错误。
所以模板的声明和定义要都包含在头文件中。 预编译时就会把模板包含到文件中。
compare.h

template<typename T>
bool compare(T a, T b);

compare.cpp

#include "compare.h"

template<typename T>
bool compare(T a, T b)
{
	return a > b;
}

main.cpp

#include "compare.h"

int main()
{
	compare(10, 20);
}

在这里插入图片描述

函数模板的非类型参数

函数的非类型参数都是常量,只能使用,不能修改。如:

#include <iostream>
using namespace std;

template<typename T, int SIZE>
void sort(T* arr)
{
	for (int i = 0; i < SIZE - 1; i++)
	{
		for (int j = 0; j < SIZE - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				T tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	int arr[] = { 4,5,1,3,6,7,2,8,9 };
	const int size = sizeof(arr) / sizeof(arr[0]);
	sort<int, size>(arr);

	for (int i = 0; i < size ; i++)
	{
		cout << arr[i] << " ";
	}
}

调用模板函数传参时必须要穿常量,否则编译不通过。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-29 11:55:13  更:2022-04-29 11:56:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 22:22:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码