知识点6 函数模板
C++的特点:封装、继承、多态
也是C++的特点:面向对象编程、泛型编程
案例:
#include <iostream>
using namespace std;
void swapInt(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
return;
}
void swapChar(char &a, char&b)
{
char tmp = a;
a = b;
b = tmp;
return;
}
//函数模板templa是关键字
//T由系统自动推导或者用户指定
template<typename T>
void mySwap(T &a, T&b)
{
T tmp;
tmp = a;
a = b;
b = tmp;
}
int main()
{
int data1 = 10, data2 = 20;
cout << "data1 = " << data1 << ", data2 = " << data2 << endl;
swapInt(data1,data2);
cout << "data1 = " << data1 << ", data2 = " << data2 << endl;
char data3 = 'a', data4 = 'b';
cout << "data3 = " << data3 << ", data4 = " << data4 << endl;
swapChar(data3,data4);
cout << "data3 = " << data3 << ", data4 = " << data4 << endl;
mySwap(data1,data2);//自动推导出T为int
mySwap(data3,data4);//自动推导出T为char
cout << "data1 = " << data1 << ", data2 = " << data2 << endl;
cout << "data3 = " << data3 << ", data4 = " << data4 << endl;
return 0;
}
用户指定T的类型
- mySwap<int>(data1,data2);//用户指定T为int
通过使用模板是为了实现泛型,可以减轻编程的工作量,增加函数的重用性。
函数模板和普通函数的区别
函数模板不允许自动类型转换
C++编译器优先考虑普通函数,但是也可以通过空模板实参列表的语法限定编译器只能通过模板匹配。
函数模板也可以重载
案例2:函数模板调用的时机
#include <iostream>
using namespace std;
void myswap(int &a, int &b)
{
cout << "普通函数" << endl;
int tmp = a;
a = b;
b = tmp;
return;
}
template<typename T>
void mySwap(T &a, T&b)
{
cout << "函数模板" << endl;
T tmp;
tmp = a;
a = b;
b = tmp;
}
int main()
{
int data1 = 10, data2 = 20;
char data3 = 'a';
cout << "data1 = " << data1 << ", data2 = " << data2 << endl;
//模板函数和普通函数都识别的情况下优先选择普通函数
myswap(data1,data2);
cout << "data1 = " << data1 << ", data2 = " << data2 << endl;
myswap<int>(data1,data3);
return 0;
}
知识点7 使用函数模板进行排序
#include <iostream>
#include <cstring>
using namespace std;
template<typename T>
void myPrintArrayTemplate(T* arr, int len)
{
int i = 0;
for(i=0;i<len;i++)
cout << arr[i] << " " ;
cout <<endl;
}
template<typename T>
void mySortArrayTemplate(T* arr, int len)
{
int i = 0, j = 0;
for(i=0;i<len-1;i++)
{
int min = i;
for(j=min+1;j<len;j++)
{
if(arr[min] > arr[j])
min = j;
}
if(min != i)
{
T tmp = arr[min];
arr[min] = arr[i];
arr[i] = tmp;
}
}
}
int main()
{
char str[] = "hello template";
int arr[] = {5,7,3,5,6,4,9,1,10};
int arr_len = sizeof(arr)/sizeof(arr[0]);
//用函数模板遍历数组
myPrintArrayTemplate(str,strlen(str));
myPrintArrayTemplate(arr,arr_len);
//用模板函数对数组排序
mySortArrayTemplate(str,strlen(str));
mySortArrayTemplate(arr,arr_len);
//用模板函数遍历数组
myPrintArrayTemplate(str,strlen(str));
myPrintArrayTemplate(arr,arr_len);
return 0;
}
知识点8 函数模板具体化
#include <iostream>
using namespace std;
class Person
{
public:
int a;
int b;
Person(int a, int b)
{
this->a = a;
this->b = b;
cout << "构造函数" << endl;
}
~Person()
{
cout << "析构函数" << endl;
}
};
ostream& operator<<(ostream &out, Person &ob)
{
out << "a = " << ob.a << ", b = " << ob.b;
}
template<typename T>
T& myMax(T &a, T &b)
{
return a>b ? a:b;
}
//方法一:提供函数模板具体化
template<> Person& myMax(Person &ob1, Person &ob2)
{
return ob1.a>ob2.b ? ob1:ob2;
}
int main()
{
Person ob1(10,20);
Person ob2(100,200);
cout << ob1 << endl;
cout << ob2 << endl;
cout << myMax(ob1,ob2) << endl;
return 0;
}
知识点9 类模板
#include <iostream>
using namespace std;
//类模板
template<class T1, class T2>
class Data
{
private:
T1 name;
T2 num;
public:
Data(T1 name, T2 num)
{
this->name = name;
this->num = num;
cout << "有参构造" << endl;
}
~Data()
{
cout << "析构函数" << endl;
}
void showData()
{
cout << "name = " << this->name << " num = " << this->num <<endl;
}
};
int main()
{
//类模板不能进行类型推导
Data <string,int>ob1("阿尔贝尔",114514);
ob1.showData();
Data <int, string>ob2(17,"伊利斯");
ob2.showData();
return 0;
}
知识点10 类模板作为函数的参数
#include <iostream>
using namespace std;
//类模板
template<class T1, class T2>
class Data
{
friend void addData(Data<string,int> &ob);
private:
T1 name;
T2 num;
public:
Data(T1 name, T2 num)
{
this->name = name;
this->num = num;
cout << "有参构造" << endl;
}
~Data()
{
cout << "析构函数" << endl;
}
void showData()
{
cout << "name = " << this->name << " num = " << this->num <<endl;
}
};
//类模板做函数参数
void addData(Data<string,int> &ob)
{
ob.name += "_shawodverse";
ob.num += 100;
return;
}
int main()
{
Data<string, int> ob("阿尔贝尔", 114514);
addData(ob);
ob.showData();
return 0;
}
知识点11 类模板派生出普通类
#include <iostream>
#include <cstring>
using namespace std;
//类模板
template<class T>
class Base
{
private:
T num;
public:
Base(T num)
{
this->num = num;
cout << "有参构造" << endl;
}
~Base()
{
cout << "析构函数" << endl;
}
void showNum(void)
{
cout << "num = " << this->num <<endl;
}
};
//类模板派生出普通类 必须给基类指定类型
class Son1:public Base<int>
{
public:
Son1(int a):Base<int>(a)
{
cout << "Son1构造" << endl;
}
};
class Son2:public Base<string>
{
public:
Son2(string a):Base<string>(a)
{
cout << "Son2构造" << endl;
}
};
int main()
{
Son1 ob1(100);
ob1.showNum();
Son2 ob2("ssdt");
ob2.showNum();
return 0;
}