模板——函数模板

概念:建立通用的模具,提高复用性。。

特点:

● 模板不能被直接使用,他只是一个框架

● 模板是通用,但不是万能

C++中的一种编程思想称为泛型编程,主要利用的技术就是模板

C++提供两种模板机制:函数模板类模板


函数模板作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体指定,用一个虚拟的类型来代表。。。

语法:

写完模板声明后,后面就要跟着写函数的声明或者定义

template——声明创建模板

typename——表示其后面的符号是一种数据类型,可用class(类模板,当然可以都写class)代替

T——通用的数据类型,名称可替换,通常为大写字母

如:T func(T a)-->【参考void func(int a)】

案例引入:

 

发现逻辑相同,因此我们可以创建一个模板实现各种类型的数据交换。。

例子:

①创建模板

 

 ②采用模板实现:

1——自动类型推导(直接塞参数,编译器自动推导类型)

 

2——显示指定类型

 

其中中括号内的int是告诉编译器,用int替代T(即告知编译器数据类型)


函数模板的注意事项:

● 自动推导:必须推导出一致的数据类型T才可以使用。

● 模板必须要确定出T的数据类型才能使用。。

关于第一点(编译器推导不出一致的T类型):

 

关于第二点(编译器不知道你在干嘛):

 

第二点的解决办法(强制指定数据类型):

 


练手1:

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

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

采用char数组和int数组进行测试

复制代码
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 //从大到小,采用选择算法
 6 
 7 template<class T>   //交换数据函数模板
 8 void mySwap(T &a, T &b){
 9     T temp = a;
10     a = b;
11     b = temp;
12 }
13 
14 template<class T>   //排序函数模板,采用选择算法
15 void mySort(T arr[], int len){
16     for(int i = 0; i < len; i++){
17         int max = i;    //认定最大值的下标
18         for(int j = i + 1; j < len; j++){   //j = i + 1表示不用再从自身及前面已经排序好的数再进行比较
19             //认定的最大值比遍历的值要小,说明j下标的元素才是真正的最大值
20             if(arr[max] < arr[j]){
21                 max = j;    //更新最大值下标
22             }
23         }
24         if(max != i){
25             //交换下标为max和i的元素
26             mySwap(arr[max], arr[i]);
27         }
28     }
29 }
30 
31 template<class T>   //打印数组模板
32 void printArray(T arr[], int len){
33     for (int i = 0; i < len; i++){
34         cout << arr[i] << " ";
35     }
36     cout << endl;
37 }
38 /////////////////////////////////////////////////////
39 void test01(){
40     //char数组
41     char charArr[] = "badcfehiz";
42     int num = sizeof(charArr) / sizeof(char);
43     mySort(charArr, num);
44     printArray(charArr, num);
45 }
46 
47 void test02(){
48     //int数组
49     int intArr[] = {8,5,9,2,4,1,35,15,94,100};
50     int num = sizeof(intArr) / sizeof(int);
51     mySort(intArr, num);
52     printArray(intArr, num);
53 }
54 
55 int main(){
56     test01();
57     test02();
58     system("pause");
59     return 0;
60 }
复制代码

普通函数和函数模板的区别(是否存在自动类型转换,也叫隐式类型转换):

● 普通函数调用时可以发生自动类型转换(隐式类型转换)

● 函数模板调用时,若采用自动类型推导,则不会发生隐式类型转换

● 如果采用显示指定类型的方式,可以发生隐式类型转换

例子(别忘了在main函数中调用test函数):

①此处把c的char类型变量自动转换成int类型的c(ASCII码),再进行计算:

 

②模板自动推导不能采用自动类型转换(编译器没法给你统一化):

 

③显示指定类型(此处指定了int类型)可以存在自动类型转换:

 


普通函数与函数模板调用规则(问题来源于普通函数和函数模板能够重名)

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

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

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

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

1.①如果普通函数只是个声明,而函数模板有完整的实现,那么编译器依旧会调用普通函数,并且给你报错。。

2.①空模板强制调用语法:函数名<void>(参数列表);

如:

 

3.①函数模板也能发生重载:

 

4.①

 

此时主函数体内调用:

 

我们知道,普通函数存在隐式类型转换(ASII码),此时这俩个模板编译器都可以调用。。

但是普通函数还需要把char类型自动转换为int类型,编译器嫌麻烦,不如直接用模板替换成char类型更快。。

因此,这类情况下编译器会优先调用模板函数。。


模板的局限性

● 切记,模板的通用性不是万能的,部分特定的数据类型需要用具体化方式做实现。。

例如(当我们往这个模板传递一个数组的时候,就不能实现了):

 

想要实现自定义的数据类型进行某些处理(比如赋值,比较大小等),C++有两种方法可以实现:

1.运算符重载(操作多的时候很麻烦)

2.提供具体化的目标重载模板函数(运行时会优先调用)

关于第二点的例子:

复制代码
 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 class Person{
 6 public:
 7     Person(string name, int age){
 8         this->m_name = name;
 9         this->m_age = age;
10     }
11     string m_name;
12     int m_age;
13 };
14 
15 template<class T>
16 bool myCompare(T &a, T &b){
17     if(a == b){
18         return true;
19     }
20     else{
21         return false;
22     }
23 }
24 
25 template<> bool myCompare(Person &a, Person &b){  //具体化实现Person,具体化会被优先调用
26     if(a.m_name == b.m_name && a.m_age == b.m_age){
27         return true;
28     }
29     else{
30         return false;
31     }
32 }
33 
34 void test1(){
35     int a = 10;
36     int b = 10;
37     bool ret = myCompare(a,b);
38     if(ret){
39         cout << "两者相等" << endl;
40     }
41     else{
42         cout << "两者不相等" << endl;
43     }
44 }
45 
46 void test2(){
47     Person p1("Tom",11);
48     Person p2("Tom",12);
49 
50     bool ret = myCompare(p1,p2);
51     if(ret){
52         cout << "两者相等" << endl;
53     }
54     else{
55         cout << "两者不相等" << endl;
56     }
57 }
58 
59 int main(){
60     test1();
61     test2();
62     system("pause");
63     return 0;
64 }
复制代码

学习目标不是为了写目标,是为了咱们后面在STL能够白嫖系统的代码。。

 

posted @   Morning枫  阅读(150)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示