首页 > 其他分享 >模板——函数模板

模板——函数模板

时间:2022-12-01 21:12:26浏览次数:37  
标签:类型转换 函数 int 数据类型 编译器 模板

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

特点:

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

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

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能够白嫖系统的代码。。

 

标签:类型转换,函数,int,数据类型,编译器,模板
From: https://www.cnblogs.com/MorningMaple/p/16909721.html

相关文章

  • 实验6 模板类和文件I/O
    实验任务3#include<iostream>#include<fstream>#include<array>#defineN5intmain(){usingnamespacestd;array<int,N>x{97,98,99,100,101......
  • 窗口函数综训
    1.累加力扣534:关键点:sum(games_played)over(partitionbyplayer_idorderbyevent_date)--滑动累加求和,指向性明显,用sum()...over()...窗口函数。注:orderby后......
  • 什么是虚函数
    虚函数是指:在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数,即被virtual关键字修饰的成员函数;格式为“virtual函数返回类型函数名(参数表){函数体}”......
  • 浅谈C++模板机制
    一、    什么是模板?1.模板(Template)可以看做成对于某一类问题一种通用的解决方案,而实现的具体细节则需要根据实际问题对模板做出调整和优化。2.如我们在使用Word进......
  • SpringBoot过滤器工具类解决跨域问题模板
    放入目录config即可@ConfigurationpublicclassCorsConfigimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestreq,ServletResponseres,F......
  • vue生命周期及钩子函数
    1.什么是vue生命周期vue生命周期指实例从开始创建到销毁的过程,在整个生命周期中,它提供了一系列事件,可以让我们在事件触发时注册js方法。在这些方法中,this指向的......
  • 实验6-模板类和文件
    task3:task3.1.cpp1#include<iostream>2#include<fstream>3#include<array>4#defineN55intmain()6{7usingnamespacestd;8array<int......
  • Oracle开窗函数rank() over(partition by ... order by ... desc)
    原文地址:https://www.cnblogs.com/LoveShare/p/16408656.html1.创建表 --CreatetablecreatetableTEST(IDNUMBER(10)notnull,NAMEVARCHAR2(50),......
  • 缩短箭头函数的技巧
    https://dmitripavlutin.com/JavaScript-arrow-functions-shortening-recipes/使用箭头语法,你可以定义比函数表达式短的函数。在某些情况下,你可以完全省略:参数括号 (param1......
  • C++学习笔记——内联函数
    //#include<iostream>//usingnamespacestd;////#defineSUM(x)((x)*(x))//定义一个宏参数//////inlinevoidfun(inti)//{//cout<<(i*......