模板编程也可以叫做泛型编程,忽略数据类型的一种编程方式
//求最值问题 int Max(int a,int b) { return a>b?a:b; } double Max(int a,int b) { return a>b?a:b; } string Max(string a,string b) { return a>b?a:b; } //引入模板编程 template //告诉编译器,下面会用到一个未知类型叫做type type Max(type a,type b) { return a>b?a:b; }
模板代码
#include using namespace std; template type Max(type a, type b) { return a > b ? a : b; } //typename 可以用class 替换 template void print(T data) { cout << data << endl; } int main() { //隐式调用 cout << Max(1, 2) << endl; cout << Max(1.1, 2.2) << endl; //string 和char* 有区别 cout << Max(string("1ILoveyou"), string("2IMissyou")) << endl; //显示调用 <>传类型的参数 cout << Max(1, 2) << endl; //type=int a=1 b=2 cout << Max(string("1"), string("2")) << endl; cout << Max(1.2, 1.3) << endl; return 0; }
函数模板和普通函数
函数模板和函数模板
#include using namespace std; //No.1 模板与普通函数 int Max(int a, int b) { cout << "普通函数..." << endl; return a > b ? a : b; } template T Max(T a, T b) { cout << "模板" << endl; return a > b ? a : b; } //No.2 模板与模板 template void print(type1 one, type2 two, type3 three) { cout << "三只" << endl; } template //type1=int type2=double void print(type1 one, type1 two, type2 tow) //int int double { cout << "两只" << endl; } template void print(type one, type two, type three) { cout << "一只" << endl; } int main() { cout << Max(1, 2) << endl; //显式调用,百分百调用模板 cout << Max(1, 2) << endl; //优先调用类型确定的函数 cout << "显示调用" << endl; print(1, 1.1, string("23")); print(1, 1, 1.22); print(1, 2, 3); cout << "隐式调用" << endl; print(1, 1, 2); //需要传参越少先调用 print(1, 1, string("sdsd")); print(1, 1.11, string("sdsd")); //只有一种选择 return 0; }
//这种不叫做模板类型 class MM { public: template void print(T data) { cout << data << endl; } protected: }; int main() { MM mm; mm.print(1); mm.print("string"); return 0; }
函数模板缺省和函数参数的缺省是一样的规则
//函数模板缺省 template void printData(type1 one, type2 two) { cout << one << endl; cout << two << endl; } int main() { printData(1, 1.22); printData(1, string("dsfsdf")); return 0; }
//函数模板传常量 template void printArray(T* array) { for (int i = 0; i < size; i++) { cout << array[i] << " "; } cout << endl; } int main() { int num[3] = { 1,2,3 }; printArray(num); //下面代码报错 //int length = 3; //printArray(num); string str[4] = { "sdds","sd","sdsd" ,"sdds"}; printArray(str); return 0; }
怎么写类模板
类模板不是一个完整类型,所以任何用到类名的地方都需要用类名<未知类型>的方式使用
怎么去使用类模板,类模板必须采用显式调用方式
类模板在多文件中不能分开写
可以写在.hpp文件中(声明和实现都在一起)
#include #include
特化的目的是为了适应不同数据的不同处理
#include using namespace std; template class Data { public: Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three) {} void printData() { cout << (one + two + three) << endl; } private: _Ty1 one; _Ty2 two; _Ty3 three; }; //局部特化 //两个数据,打印两数之差 template class Data<_Ty1,_Ty1,_Ty2> { public: Data(_Ty1 one, _Ty2 two) :one(one), two(two){} void printData() { cout << (one -two) << endl; } private: _Ty1 one; _Ty2 two; }; //只有一个数据,打印数据 template class Data<_Ty1,_Ty1,_Ty1> { public: Data(_Ty1 one) :one(one){} void printData() { cout << one << endl; } private: _Ty1 one; }; //完全特化 template <> class Data { public: Data(string one,string two,string three):one(one),two(two),three(three) { } void printData(); private: string one; string two; string three; }; void Data::printData() { cout << one << " " << two << " " << three << endl; } int main() { Data data1(1); data1.printData(); Data data2(2, 1); data2.printData(); Data data3(1, 1.1, 1.2f); data3.printData(); Data data4("dsd","sdfd","sdfdsf"); data4.printData(); return 0; }
模板操作自定义关键点在于重载
#include #include using namespace std; class MM { public: MM() = default; MM(string name, int age) :name(name), age(age) {} friend ostream& operator<<(ostream& out, const MM& object) { out << object.name << " " << object.age; return out; } private: string name; int age; }; template void printData(_Ty data) { cout << data << endl; } template class Data { public: //_Ty1=MM, _Ty2=int, _Ty3=int Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three) { } void printData() { cout << one << " " << two << " " << three << endl; } private: _Ty1 one; _Ty2 two; _Ty3 three; }; int main() { printData(1); printData("string"); MM mm = { "小芳",18 }; printData(mm); Data data(MM("小芳",18),98,99); data.printData(); Data mmData(MM("小芳", 18), MM("小芳", 18), MM("小芳", 18)); mmData.printData(); return 0; }
#include using namespace std; template class Data { public: Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three) {} void printData() { cout << one << " " << two << " " << three << endl; } friend ostream& operator<<(ostream& out, Data<_Ty1, _Ty2, _Ty3>& object) { out << object.one << " " << object.two << " " << object.three; return out; } protected: _Ty1 one; _Ty2 two; _Ty3 three; }; template class Info { public: Info(_Ty1 one, _Ty2 two) :one(one), two(two) {} void printData() { cout << one << " " << two << endl; } //template 类中实现不需要修饰了,会出现重定义问题 friend ostream& operator<<(ostream& out, Info<_Ty1, _Ty2>& object) { out << object.one << " " << object.two << " "; return out; } protected: _Ty1 one; _Ty2 two; }; template class Student { public: Student(_Ty1 one) :one(one) {} void printData() { cout << one << endl; } protected: _Ty1 one; }; int main() { Data data(1,1,1); //Data Info info(1, 2); //Info Info, Data> test1(Data(1, 1, 1), Data("ds", "sd", "sds")); //起别名 using type1 = Data; using type2 = Data; //别名版本 Infotest2(type1(1, 1, 1), type2("ds", "sd", "sds")); Data, Info, Info> test3(Info(1,"sd"), Info("sdds","dsds"),Info(1,1.11)); test1.printData(); test2.printData(); test3.printData(); Student, Info, Info>> stu(Data, Info, Info> (Info(1,1), Info(1,"sdsd"), Info("sds","sdsd"))); stu.printData(); return 0; }