函数模板
什么是模板:
把类型当作未知量来处理,可以忽略类型的影响。
申明模板方法:template
存在多个未知数据类型template
其中typename可以换成class
tmplate
调用函数模板:
隐式调用:正常函数传参即可调用
显示调用 :函数名<类型名>(参数)
函数模板的两种形态:
1.普通函数当作模板
2.类的成员函数是函数模板
函数模板特殊写法:
1.缺省写法
2.存在一个常量类型
#includeusing namespace std; //int Max(int a, int b) { // return a > b ? a : b; //} //string Max(string a, string b) { // return a > b ? a : b; //} //引入模板概念template template //标准格式 _Ty Max(_Ty a, _Ty b) { return a > b ? a : b; } template void print(_Ty1 a, _Ty2 b) { cout << a << endl; cout << b << endl; } //类的成员函数是函数模板 class Girl { public: template void print(_Ty data) { cout << data << endl; } template void printData(_Ty data); protected: string name; int age; }; template void Girl::printData(_Ty data) {//类中申明,类外实现前缀不能省略 cout << data << endl; } //缺省写法 template void printData(_Ty1 one, _Ty2 two) { cout << one << "t" << two << endl; } //存在传常量写法 template void printArray(_Ty1 array) {//_Ty1=int*,size=3(必须显示调用,除废用缺省) for (int i = 0; i < size; i++) { cout << array[i]; } cout << endl; } //size_t无符号整形的别名 void testFunc() { printData("string", 1231); //可以类型缺省,但是参数不能少 printData ("string", 123); int array[3] = { 1,2,3 }; printArray (array); } int main() { cout << Max(1, 2) << endl;//隐式调用 cout << Max("string1", "string2") << endl;//隐式调用 cout << Max(1.1,2.5) << endl;//隐式调用 cout << Max ("abc", "def") << endl;//显示调用 print ("1234", "4321"); print ("1234", 4321); //调用类中成员函数模板 Girl girl; girl.print(123); girl.print ("ILoveYou"); //模板函数也可以缺省 return 0; }
类模板(用在数据结构上比较多)
如何生成一个类模板:
template
public:
protected:
}
只要被template修饰了就是模板类型,至于是否用了未知类型,没有关系
类模板的调用:
必须采用显示调用
类模板不是一个实际的类,所以所有用到类名的地方,都需要使用类名<未知类型>方式使用
多文件中,类模板中的声明和实现一定是在一起的,不能分开写。
和函数模板一样可以传常量
#includeusing namespace std; //template<>class Data { //public: //protected: //}; template class MM { public: MM(){}//构造函数正常写 MM(string name):name(name){} void print(); protected: string name; }; //在类外实现 template void MM<_Ty>::print() { cout << "类模板" << endl; } //继承 template class Girl :public MM<_Ty> { public: Girl(string name) :MM<_Ty>(name) { } protected: }; template class Data { public: Data(_Ty1 one,_Ty2 two):one(one),two(two){} void print(); protected: _Ty1 one; _Ty2 two; }; template void Data<_Ty1,_Ty2>::print() { cout << one << endl; cout << two << endl; } int main() { //MM mm;模板类直接创建对象报错 //必须采用显示调用 MM mm1; MM mm2; Girl girl("loveyou"); Data data1("张三", 20); data1.print(); Data data2(12, 21); data2.print(); return 0; }
模板传入自定义类型
基本自定义类型:
自定义类型也是模板:
模板传入自定义类型,关键点就在运算符重载
#includeusing namespace std; class MM { public: MM(string name,int age):name(name),age(age){} friend ostream& operator<<(ostream& out,const MM& mm) { out << mm.name << " " << mm.age << endl; return out; } bool operator>(MM& mm)const { return this->age > mm.age; } protected: string name; int age; }; template void print(_Ty one){ // 二元"<<":没有找到接受“_Ty”类型的右操作数的运算符(或没有可接受的转换) //对象不能直接打印 cout << one << endl; } template _Ty Max(_Ty a,_Ty b) { return a > b ? a : b; } template class Node { //using LPtype = Node<_Ty>; public: Node(_Ty data,Node<_Ty>* next):data(data),next(next){} Node<_Ty>* getNext() { return next; } _Ty getData() { return data;//MM对象返回值是常属性,所以<<重载要加const!!!! } protected: _Ty data; //LPtype* next; Node<_Ty>* next; }; template class List { public: List() { headNode = nullptr; } void insertList(_Ty data) { headNode = new Node<_Ty>(data, headNode); } void printData() { Node<_Ty>* pMove = headNode; while (pMove != nullptr) { cout << pMove->getData() << endl; pMove = pMove->getNext(); } } protected: Node<_Ty>* headNode; }; void testList(){ List list; list.insertList(1); list.insertList(2); list.insertList(3); list.printData(); List mmList; mmList.insertList(MM("小花", 21)); mmList.insertList(MM("小华", 12)); mmList.insertList(MM("晓华", 32)); mmList.printData(); } int main() { //函数模板传入自定义类型 print (12); print("Ilobeyou"); print(MM("mm", 19)); MM girl1("张三", 21); MM girl2("李四", 25); MM result = Max (girl1, girl2);//也可以隐式调用 cout << result; testList(); return 0; }
模板的嵌套(类)
明白类型是什么即可,可以适当运用using语法起别名,简化代码。
#includeusing namespace std; template class MM { public: MM(_Ty1 one,_Ty2 two):one(one),two(two){} friend ostream& operator<<(ostream& out,const MM& mm) { out << mm.one << " " << mm.two; return out; } protected: _Ty1 one; _Ty2 two; }; template class Data { public: Data(_Ty1 one, _Ty2 two) :one(one), two(two) {} void print() { cout << one << " " << two << endl; } protected: //MM<_Ty1, _Ty2> mmData; _Ty1 one; _Ty2 two; }; void testFunc() { //_Ty1类型是MM //_Ty类型是MM Data , MM > data(MM ("小强",18),MM ("大强",20.0)); data.print(); } template void print(_Ty data) { cout << data << endl; } int main() { print(MM ("晓华", 12)); print >(MM ("张三", 40)); using MMType = MM (MMType("李四", 28)); testFunc(); return 0; }
函数模板重载
#includeusing namespace std; void print(int a,string b) { cout << "普通函数" << endl; } template void print(_Ty1 a, _Ty2 b) { cout << "两个类型模板函数" << endl; } template void print(_Ty a,_Ty b) { cout << "一个类型模板函数" << endl; } int main() { print (12, "显示调用一定调用模板的"); print(21, string("优先调用适应的普通函数")); //当两个模板同时成立,优先调用类型相似度高的那个 print(12, 12); return 0; }
类模板特化
局部特化:
完全特化:
#include#include using namespace std; //两个未知类型 template class MM { public: MM(_Ty1 one,_Ty2 two):one(one),two(two){} void print(){ cout << one << " " << two << endl; } protected: _Ty1 one; _Ty2 two; }; class Data { public: Data(int a,int b):a(a),b(b){} void print() { cout << a << " " << b << endl; } protected: int a; int b; }; //局部特化,特殊化 template class MM<_Ty,_Ty> {//特化产生的类,类名要用:类名<类型>方式使用 public: MM(_Ty one, _Ty two) :one(one), two(two) {} void print() { //cout << one << " " << two << endl; one.print(); two.print(); cout << "特殊化" << endl; } protected: _Ty one; _Ty two; }; //完全特化(类型全部具体化) //在折叠参数中有用 template<>class MM { public: MM(string one,string two):one(one),two(two){} void print() { cout << "完全特化" << endl; cout << one << " " << endl; } protected: string one; string two; }; int main() { MM mm1("张三", 48); //MM mm2("李四","翠花"); MM dMM(Data(1,2),Data(3,4)); dMM.print(); return 0; }



