什么叫泛型编程?1. 参数类型化。 2. 模板
模板概念
c++提供了函数模板,所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数就成为函数模板。凡是函数体相同的函数都可以用这个模板代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现不同函数的功能。
- c++提供两种模板机制:函数模板和类模板
- 类属–类型参数化,又称参数模板
总结
- 模板把函数或类要处理的数据类型参数化,表现为参数的多态性,成为类属
- 模板用于表达逻辑结构相同,但具体数据元素类型不同的数据对象的通用行为。
函数模板
-
template <class / typename T>
告诉编译器紧跟的代码出现T不要报错 -
类型也需要传入,类型参数化
-
自动类型推导
-
显示指定类型
#include<iostream>using namespace std;//交换int 类型的两个文字void mySwaoInt(int &a, int &b){int tmp = a;a = b;b = tmp;}//交换double的数据void mySwapDouble(double &a, double &b){double tmp = a;a = b;b = tmp;}//类型,逻辑又非常相似//类型参数化,泛型编程--模板技术template<class T>//告诉编译器 下面如果出现T不要报错,T是一个通用的类型void mySwap(T &a, T &b){T tmp = a;a = b;b = tmp;}//template<typename T> 等价于template<class T>template<typename T>void mySwap2(){};void test01(){int a = 10;int b = 20;char c1 = 'c';//mySwaoInt(a, b);//1. 自动类型推导,必须有参数类型才可以推导//2.参数类型必须一样//mySwap(a, c1);//推导不出来T,所以不能运行mySwap(a, b);//2.显示指定类型mySwap<int >(a, b);//模板必须要指定出T才可以使用mySwap2<double>();cout << "a=" << a << endl;cout << "b=" << b << endl;double c = 3.14;double d = 1.1;//mySwaoInt(a, b);mySwap(c, d);}int main(){test01();system("pause");return 0;}
利用模板实现数组排序
#include<iostream>using namespace std;//对char 和 int 数组进行排序 ,排序规则 从大到小 利用选择排序template<class T>void mySwap(T &a, T &b){T tmp = a;a = b;b = tmp;}template<class T>void mySort( T arr[], int len){//选择排序for (int i = 0; i < len; i++){int max = i;for (int j = i + 1; j < len; j++){if (arr[max] < arr[j]){//交换 下标max = j;}}if (max != i){//交换数据mySwap(arr[max], arr[i]);}}}//输出数组元素的模板template <class T>void printArray(T arr[], int len){for (int i = 0; i < len; i++){cout << arr[i] << " "; }cout << endl;}void test01(){char charArr[] = "helloword";int num = sizeof(charArr) / sizeof(char);mySort(charArr, num);printArray(charArr, num);int intArr[] = { 1, 4, 100, 34, 55 };int num2 = sizeof(intArr) / sizeof(int);mySort(intArr, num2);printArray(intArr, num2);}int main(){test01();system("pause");return 0;}
函数模板和普通安徽念书在一起调用规则
区别 :普通函数可以进行隐式类型转换,模板不行。
-
c++编译器优先考虑普通函数
-
可以通过空模板实参列表的语法限定编译器只能通过模板匹配
-
函数模板可以像普通函数那样可以被重载
-
如果函数模板可以产生一个更好的匹配,那么选择模板
#include<iostream>using namespace std;//1. 普通模板与函数模板区别template <class T>T myPlus(T a, T b){return a + b;}int myPlus2(int a, int b){return a + b;}void test01(){int a = 10;int b = 20;char c = 'c';//a=97.c=99//myPlus(a, c);//类型推导不出来cout << myPlus2(a, c) << endl;//10+99 普通函数 可以进行隐式类型转换}//2. 普通函数和函数模板的调用规则template<class T>void myPrint(T a, T b){cout << "模板调用的myPrint" << endl;}template<class T>void myPrint(T a, T b,T c){cout << "模板调用的myPrint(a,b,c)" << endl;}void myPrint(int a, int b){cout << "普通的函数调用myPrint" << endl;}void test02(){int a = 10;int b = 20;//如果出现重载,优先使用普通模板的调用,如果没有实现普通函数,出现错误//myPrint(a, b);//如果想强制调用模板,那么可以使用空参数列表myPrint<>(a, b);//3. 函数模板可以发生重载int c = 30;myPrint(a, b, c);//如果函数模板可以产生更好的匹配,那么优先使用函数模板char e = 'c';char d = 'd';myPrint(c, d);}int main(){//test01();test02();system("pause");return 0;}