模板:把类型当做未知量
不因类型的不同而需要重写代码。
int Max(int a, int b) { return a > b ? a:b; } char Max(char a, char b) { return a > b ? a : b; }
1 函数模板
对于实现相同函数功能,因类型不同需要重写函数体而引入模板
1.1. 模板声明
template
1.2 单个多个未知类型
//引入模板,告诉编译器 下面的代码未知类型_Ty // 单个未知类型 template_Ty Max(_Ty a, _Ty b) { return a > b ? a : b; } //多个未知类型 中间用逗号分隔 //下面两行可以写为一行//template void print(_Ty1 one, _Ty2 two, _Ty3 three) template void print(_Ty1 one, _Ty2 two, _Ty3 three) { cout << one << two << three; } //返回值类型为 _Ty4 template _Ty4 print(_Ty1 one, _Ty2 two, _Ty3 three) { cout << one << two << three; }
1.3 函数模板调用
隐式调用 :正常的函数传参即可调用
显示调用:函数名<类型名>(参数)
显示调用所传参数类型必须与类型一致
template_Ty Max(_Ty a, _Ty b) { return a > b ? a : b; } template void printTwo(_Ty1 a, _Ty2 b) { cout< void printSum(_Ty1 one,_Ty2 two) { cout << one << " " << two << endl; } int main() { //隐式调用 cout << Max(1, 2) << endl; cout << Max("aaa", "nmmm") << endl; //显示调用 cout << Max ("abf", "aaa") << endl; cout< (1.1, 1.2)< ("sss", 12); //缺省情况 printSum("lalal",222);//隐式调用不明显 printSum ("wuwu",1111); //显示调用 类型调用是可以缺省不写,但参数必须写 return 0; }
//存在传常量写法 //size_t: unsigned int 的别名 templatevoid printArray(_Ty1 array) //_Ty1=int * ,size=3 { for (int i = 0; i < size; i++) { cout << array[i]; } cout << endl; } void testFunc() { int array[3] = { 1,2,3 }; //没有做缺省必须显示调用 printArray (array); //做了缺省可以隐式调用 printArray(array); //不能传入变量,只能传入常量,函数模板如果存在变量的情况下 //int size = 3; //printArray (array); } int main() { testfunc(); return 0; }
1.4 函数模板的两种形态
1 普通函数当做函数模板
以上的例子全是普通函数当做函数模板
2 类的成员函数是函数模板
class MM { public: templatevoid print(_Ty data) { cout << data << endl; } //去类外实现 template void printdata(_Ty data); protected: }; template void MM::printdata(_Ty data) { cout << data << endl; } int main() { //类中的成员函数 MM mm1; mm1.print(12); mm1.printdata(1234); mm1.printdata ("hahhaha"); return 0; }
2 类模板
用template修饰的类就是类模板,用不用未知类型没关系
必须采用显示调用
类模板不是一个实际类型,所以所有用到类名的地方都需要使用类名<未知类型>方式使用
#includeusing namespace std; //没有这种写法 //template <> //class MM //{}; template class Lin { public: Lin() {} Lin(string name):name(name){} void print(); void printSum(); protected: string name; }; //类外实现 必须要加templat template void Lin<_Ty>::print() { cout << "haha" << endl; } //继承 template class boy:public Lin<_Ty> { public: //子类的构造函数写法 boy(string name) :Lin<_Ty>(name) {} }; 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() { //模板类的调用必须显示调用 Lin gg; //即使没有用到未知类型 也必须写出来 Lin gg1; Lin gg2; //Lin gg; Lin gg3("xixi"); gg3.print(); Data mmInfo("小芳", 19); mmInfo.print(); Data data(12, 11); data.print(); return 0; }
3 自定义类型当做模板参数
基本自定义类型
自定义类型也是一个模板
模板传入自定义类型,关键在于运算符重载
#includeusing namespace std; class Car { public: Car(string num,double price) :num(num), price(price) {} friend ostream& operator<<(ostream& out, const Car& object) { out << object.num << " " << object.price << endl; return out; } bool operator>(Car& object) { return this->price > object.price; } protected: string num; double price; }; template void print(_Ty one) { cout << one << endl; } template _Ty Max(_Ty one, _Ty two) { return one > two ? one : two; } template class Node { public: Node(_Ty data, Node<_Ty>* next) :data(data), next(next) {} _Ty getData() { return data; } Node<_Ty>* getNext() { return next; } protected: _Ty data; Node<_Ty>* next; //至于为什是Node<_Ty>* 看前面类模板 //正常写法 Node* next; }; template class List { public: List() { headNode = nullptr; } void insertList(_Ty data) { headNode = new Node<_Ty>(data,headNode); } void printList() { Node<_Ty>* pmove = headNode; while (pmove != nullptr) { cout << pmove->getData() << endl; pmove = pmove->getNext(); } cout << endl; } protected: Node<_Ty>* headNode; }; void testList() { List list; list.insertList(1); list.insertList(2); list.insertList(3); list.printList(); List carList; carList.insertList(Car("BYD",5000)); carList.insertList(Car("LSLS", 50000)); carList.insertList(Car("WL", 100)); carList.printList(); } int main() { //基本数据类型做参数 隐式调用 print(12); print("223"); //基本数据类型做参数 显示调用 print ("12244"); //自定义类型 print(Car("dongfeng", 2000)); Car DF("dongf",100000); Car BC("benchi",2000); Car result = Max(DF,BC); //隐式调用 // Car result = Max (DF,BC);//显示调用 结果一致 cout << result << endl; testList(); return 0; }
4 模板嵌套
明白类型是什么即可,适当可以借用using语法起别名 简化代码
#includeusing namespace std; template class Person { public: Person(_Ty1 name,_Ty2 age) :name(name), age(age) {} friend ostream& operator<<(ostream& out, const Person& p1) { out << p1.name << " " << p1.age << endl; return out; } protected: _Ty1 name; _Ty2 age; }; template class Car { public: Car(_Ty1 one, _Ty2 two) :one(one), two(two) {} void print() { cout << one << " " << two << endl; } protected: _Ty1 one; _Ty2 two; }; void testFunc() { //类模板嵌套 类与类模板嵌套 //Ty1 类型是 Person //Ty2 类型是 Person Car , Person > car(Person ("DZ",2222),Person (11,303)); car.print(); //上面两个等效下面四行 } template void print(_Ty data) { cout << data << endl; } int main() { //隐式调用 普通函数与类模板嵌套 print(Person ("太一",232)); //显示调用 print >(Person ("太一", 232)); //看起来麻烦 起别名 using PerType = Person (PerType("大古",12)); testFunc(); return 0; }
5 模板函数的重载
#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(13,"字符串解析为char*类型,调用2个模板类型"); print(12, string("优先调用适应的普通函数")); //调用 普通函数 //两个模板同时成立,优先调用类型相似度搞的那个 print (12,12);//显示调用 强类型,会调用2个类型 print(12, 12); // 隐式调用 解析成print 需要做2次匹配 解析成 print 做一次匹配 //优先调用匹配少的这种 return 0; }
6 模板特化
#include#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 << " " << two << endl; } protected: string one; string two; }; int main() { //原生模板 MM mm1("小芳", 18); mm1.print(); //局部特化模板 MM dMM(Data(1, 2), Data(3, 4)); dMM.print(); //完全特化的模板 MM mm2("小丽", "小美"); mm2.print(); tuple tp("张三", "李四"); return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)