C++笔记打卡第15天(函数模版)

server/2024/9/24 13:00:12/

1.模版

  • 模版不可以直接使用,它只是一个框架
  • 模版并不是万能的
  • C++另一种编程思想称为泛型编程,主要利用的技术就是模版
  • C++提供两种模版机制:函数模版类模版

2.函数模版

  • 作用:建立一个通用函数,函数返回值类型形参类型可以不具体指定,用一个虚拟的类型来表示。
  • 语法:template(typename T)
  • 解释:template—声明创建模版,typename—表明其后面的符号是一种数据类型,可以用class代替,T—通用的数据类型,名称可以替换,通常为大写字母
void swapInt(int &a, int &b)
{int temp = a;a = b;b = temp;
}void swapFloat(float &a, float &b)
{float temp = a;a = b;b = temp;
}// 创建模版
template<typename T>  // 声明一个模版,且T是一个通用的数据类型
void mySwap(T &a, T &b)
{T temp = a;a = b;b = temp;
}void test01()
{int a = 10;int b = 20;// swapInt(a,b);// 两种方式使用函数模版// 1.自动类型推导mySwap(a, b);// 2.显示指定类型mySwap<int>(a, b);cout << a << endl;cout << b << endl;
}

1.函数模版利用关键字template

2.使用函数模版有两种方式:自动类型推导、显示指定类型

3.模版的目的是为了提高复用性,将类型参数化

3.函数模版注意事项

  • 自动类型推导,必须推导出一致的数据类型T,才可以使用
  • 模版必须确定出T的数据类型,才可以使用
// 创建模版
template<class T>  // 声明一个模版,且T是一个通用的数据类型
void mySwap(T &a, T &b)
{T temp = a;a = b;b = temp;
}
void test01()
{int a = 10;int b = 20;char c ='c';// mySwap(a, c); // 错误,推导不出一致的T类型
}template<class T>
void fun()
{cout << "func调用" << endl;
}
void test02()
{//fun(); // 错误,模版必须确定出T的数据类型,才可以使用fun<int>();
}

4.函数模版案例

  • 利用函数模版封装一个排序的函数,可以对不同数据类型数组进行排序
  • 排序规则从大到小,排序算法为选择排序
  • 分别利用char数组和int数组进行测试
template<class T> 
void Swap(T &a, T &b)
{T temp = a;a = b;b = temp;
}// 对数组进行排序
template<class T>  // 声明一个模版,且T是一个通用的数据类型
void Sort(T array[], int len)
{for(int i=0; i<len; i++){int max = i;for (int j=i; j<len ; j++){if(array[max]<array[j]){max = j;}}if(max != i){Swap(array[i], array[max]);  // ????}}
}template<class T>
void printArray(T array[], int len)
{for(int i=0; i<len; i++){cout << array[i] << " ";}cout << endl;
}void test01()
{char charArray[] = "badcfe";int len = sizeof(charArray) / sizeof(char);Sort<char>(charArray, len);printArray<char>(charArray, len);
}void test02()
{int intArray[] = {7,5,8,6,3,4};int len = sizeof(intArray) / sizeof(int);Sort<int>(intArray, len);printArray<int>(intArray, len);
}

5.普通函数和函数模版的区别

  • 普通函数调用时可以发生隐式类型转换
  • 函数模版调用时,如果利用自动类型推导,不会发生隐式类型转换
  • 如果利用显示指定类型的方式,可以发生隐式类型转换
int Add01(int a, int b)
{return a + b;
}template<class T>
T Add02(T a, T b)
{return a + b;
}void test01()
{int a = 10;int b = 20;char c = 'c';  cout << Add01(a,c) << endl;  // 普通函数里,字符型'c'可以隐式转换为整型,ASCII码为99// 自动类型推导cout << Add02(a,c) << endl; // 错误,函数模版调用时,如果利用自动类型推导,不会发生隐式类型转换// 显示指定类型cout << Add02<int>(a,c) << endl; // 正确,利用显示指定类型的方式,可以发生隐式类型转换
}

建议使用显示指定类型的方式,调用函数模版,因为自己可以确定通用类型T

6.普通函数和函数模版的调用规则

  • 如果函数模板和普通函数都可以实现,优先调用普通函数
  • 可以通过空模板参数列表来强制调用函数模板
  • 函数模板也可以发生重载
  • 如果函数模板可以产生更好的匹配,优先调用函数模板
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 test01()
{int a = 10;int b = 20;Print(a, b);  // 1.函数模板和普通函数都可以实现时,优先调用普通函数// 2.通过 空模板 参数列表来强制调用函数模板Print<>(a, b);// 3.函数模板也可以发生重载Print(a, b, 100);  // 重载函数模版// 4.如果函数模板可以产生更好的匹配,优先调用函数模板char c1 = 'a';char c2 = 'b';Print(c1, c2); // 函数模版
}

7.模版的局限性

  • 模版并不是通用的(对自定义数据类型无效)
  • 为了解决这种问题,提供模版的重载,C++可以为这些特定的类型提供具体化的模版
class Person
{
public:Person(string name, int age){m_name = name;m_Age = age;}int m_Age;string m_name;
};// 判断两个数据是否相等
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 test01()
{int a = 10;int b = 20;bool res = Compare(a, b);cout << res << endl;
}void test02()
{Person p1("Tom", 10);Person p2("Tom", 10);bool res = Compare(p1, p2);  // 走具体化的代码cout << res << endl;
}

利用具体化的模版,可以解决自定义类型的通用化

学习模版并不是为了写模版,而是在STL能够运用系统提供的模版


http://www.ppmy.cn/server/9772.html

相关文章

网络工程师----第十一天

OSPF&#xff1a; 对称加密算法&#xff1a; 也称为私钥加密或单密钥算法&#xff0c;是一种加密方式&#xff0c;其中加密和解密使用相同的密钥。这种算法的优点包括加密解密速度快、计算量小&#xff0c;适用于大量数据的加密。然而&#xff0c;它的缺点是密钥的安全性难以保…

LeetCode 1.两数之和(HashMap.containsKey()、.get、.put操作)

给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回…

全网短剧搜索源码+短剧API接口 短剧下载 热门短剧 全开源可二开

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 pc端h5手机端全网短剧搜索前端源码分享 内含7000短剧资源(不支持在线播放&#xff09; 搜索API接口&#xff1a;文件内查看 全部短剧API接口&#xff1a;文件内查看 每日更新API接…

第十三章 使用深度和法线纹理

获取深度和法线纹理 背后的原理 深度纹理是一张渲染纹理,它里面存储的像素值不是颜色,而是一个高精度的深度值。深度值范围是[0, 1],非线性分布的。这些深度值来自于顶点变换后得到的归一化的设备坐标(NDC)。一个模型想要被绘制在屏幕上,需要把它的顶点从模型空间变换到齐…

windows 11 打包python镜像相关操作

第一步&#xff1a;Docker下载 首先先到Docker官网下载最新官方Docker for Windows链接&#xff0c;点击下载之后进行安装&#xff0c;安装好之后在cmd执行 wsl --update。 第二步&#xff1a;在电脑上打开“控制面板”->“程序”-> “启动或关闭Windows功能”。 有的…

常见面试算法题-数组二叉数

■ 题目描述 【数组二叉树】 二叉树也可以用数组来存储&#xff0c;给定一个数组&#xff0c;树的根节点的值存储在下标1&#xff0c;对于存储在下标N的节点&#xff0c;它的左子节点和右子节点分别存储在下标2*N和2*N1&#xff0c;并且我们用值-1代表一个节点为空。 给定一…

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试 一、背景介绍1.1 RW007模组简介1.2 Arduino接口简介1.3 RW007软件包简介1.4 RT-Thread env工具简介 二、创建工程2.1 新建工程2.2 添加rw007软件包2.3 打开RW007配置项2.4 启用pin驱动2.5 禁用rw007的ST…

python-基础(5)-字典

python专栏地址 上一篇: python-基础(4)-list 字典 本节主要介绍 字典初始字典的操作 一、字典简单了解 所谓字典&#xff0c;就像我们常用的字典一样&#xff0c;输入一个页码&#xff0c;就到达一页。它有两种方式创建&#xff1a; 直接写name{}namedict() gufeng {&quo…