作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的
作者主页:热爱编程的小K
专栏链接:c++欢迎各位→点赞 + 收藏 + 留言
总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
模板是一种忽略数据的一种泛型编程。把数据当做未知量,当使用的时候传入类型的一种编程方式
语法
template
//告诉编译器,接下来要用到一个未知类型是T类型
template
//等效class
template
//三个未知类型
#include
#include
using namespace std;
#if 0
int Max(int a, int b)
{
return a > b ? a : b;
}
float Max(float a, float b)
{
return a > b ? a : b;
}
double Max(double a, double b)
{
return a > b ? a : b;
}
#endif
template T1 Max(T1 a,T1 b)
{
return a > b ? a : b;
}
int main()
{
cout << Max(9, 10);
return 0;
}
- 函数模板调用
- 函数模板隐式调用
- 显示调用:函数名<未知类型>(函数参数)
- 函数模板本质就是函数传参
- 函数模板也是可以缺省
- 函数模板中存在变量
- 这种函数模板必须显示调用
- 变量传参只能传入常量
- 当函数模板和普通函数相遇
- 优先调用类型一致的普通函数
- 显示调用一定调用模板
- 函数模板重载
- 优先调用传参数目少的函数模板
#include
#include
using namespace std;
template T1 Max(T1 a, T1 b)
{
return a > b ? a : b;
}
template void print(_T1 a, _T2 b, _T3 c)
{
cout << a << "\t" << b << "\t" << c << endl;
}
template void printData(_T1 a, _T2 b, _T3 c)
{
cout << a << endl << b << endl << c << endl;
}
template _T1* createNew()
{
_T1* createNew = new _T1[size];
return createNew;
}
template _T1* createParry()
{
_T1* createNew = new _T1[size];
return createNew;
}
template void printArray2(_Ty array[])
{
for (int i = 0; i < size; i++)
{
cout << array[i] << "\t";
}
cout << endl;
}
void Func1(int a, double b, string c)
{
cout << "普通函数" << endl;
}
template void Func1(_T1 a,_T2 b,_T3 c) { cout << "三个" << endl; }
template void Func1(_T1 a, _T2 b, _T2 c) { cout << "两个" << endl; }
template void Func1(_T1 a,_T1 b,_T1 c) { cout << "一个" << endl; }
void test1()
{
//函数模板存在变量,必须显示调用
int* parry = createNew();
//变量缺省时候可以隐式调用
double* king = createParry();
int p[4] = { 1,2,3,4 };
printArray2(p);
}
void test2()
{
//函数模板重载,普通函数
Func1(1,1.11,string("king"));
Func1(1, 1.11,string("king"));
Func1(1, string("asdd"),string("kkk"));
Func1(1, 1, 1);
}
int main()
{
//隐式调用
cout << Max(1, 2) << endl;
cout << Max(1.1, 1.2) << endl;
cout << Max(string("abc"), string("abd")) << endl;
print(123, string("king"), 1.55);
//显示调用
cout << Max(1, 2) << endl;
cout << Max(string("abc"), string("abd")) << endl;
print("asdas", 123, 123.213);
//函数模板的缺省
printData(1, "dad", 1.11);
printData(1.11, 1, "dasdf");
test1();
test2();
return 0;
}
操作自定义类型的关键点就是重载
#include
#include
using namespace std;
template void printpArry(_T1 arry[],int arryNums)
{
for (int i = 0; i < arryNums; i++)
{
cout << arry[i] << endl;
}
cout << endl;
}
template void Sort(_T1 arry[], int arryNums)
{
for (int i = 0; i < arryNums; i++)
{
for (int j = 0; j < arryNums - i - 1; j++)
{
if (arry[j] > arry[j + 1])
{
_T1 temp = arry[j];
arry[j] = arry[j + 1];
arry[j + 1] = temp;
}
}
}
}
class MM
{
public:
MM(string name="", int age=0):name(name),age(age){}
friend ostream& operator<<(ostream& out,const MM& object)
{
out << object.age << "\t" << object.name << endl;
return out;
}
bool operator>(const MM& object)
{
return this->name > object.name;
}
string Getname() const { return this->name; }
int Getage() const { return this->age; }
protected:
string name;
int age;
};
template void Sort2(_T1 arry[], int arryNums,bool(*compare)(const _T1& one,const _T1& two))
{
for (int i = 0; i < arryNums; i++)
{
for (int j = 0; j < arryNums - i - 1; j++)
{
if (compare(arry[j] , arry[j + 1]))
{
_T1 temp = arry[j];
arry[j] = arry[j + 1];
arry[j + 1] = temp;
}
}
}
}
bool compareByname(const MM& one, const MM& two)
{
return one.Getname() > two.Getname();
}
bool compareByage(const MM& one, const MM& two)
{
return one.Getage() > two.Getage();
}
int main()
{
int parry[5] = { 1,20,6,7,90 };
Sort(parry, 5);
printpArry(parry, 5);
MM mm[3];
mm[0] = { "e",123 };
mm[1] = { "b",241 };
mm[2] = { "d",345 };
Sort(mm, 3);
printpArry(mm, 3);
Sort2(mm, 3,compareByage);
printpArry(mm, 3);
return 0;
}
template
修饰的类就是类模板- 模板类必须显示实例化,简单来说必须要传参
- 模板类不是一个真正的类型
- 声明和实现必须写在一起,所谓一起就是同一个文件中
- 所有用到类型的地方必须要用类名<未知类型>的用法
- 类模板特化
- 局部特化:特殊化处理,例如两个未知变成一个未知类型
- 完全特化:具体化类型
#include
#include
using namespace std;
template class Data
{
public:
void print();
static int count;
};
template int Data<_T1, _T2>::count = 0;
template void Data<_T1, _T2>::print()
{
cout << "类中模板函数" << endl;
}
//类模板的继承
template class Son : public Data<_T1, _T2>
{
public:
protected:
};
struct MMinfor
{
string name;
int age;
};
ostream& operator<<(ostream& out, const MMinfor& object)
{
out << object.age << "\t" << object.name << endl;
return out;
}
struct MMscore
{
int math;
int english;
int chinese;
};
ostream& operator<<(ostream& out, const MMscore& object)
{
out << object.math << "\t" << object.english << "\t" << object.chinese << endl;
return out;
}
template class MM
{
public:
MM(_T1 one,_T2 two):one(one),two(two){}
void print() { cout << one << "\t" << two << endl; }
protected:
_T1 one;
_T2 two;
};
void test1()
{
MM < string, int > mm("king", 19);
mm.print();
MM complaxe(1, 1);
complaxe.print();
//MMinfor info{string("zhang"), 18};
//MMscore score{ 13,14,123 };
//MM king(info, score);
MM king({ "zhang",18 }, { 31,312,453 });
king.print();
}
//类模板特化
template class A
{
public:
A(_T1 one,_T2 two,_T3 three):one(one),two(two),three(three)
{
cout << "三个类型" << endl;
}
protected:
_T1 one;
_T2 two;
_T3 three;
};
//局部特化
template class A<_T1,_T1,_T1>
{
public:
A(_T1 one, _T1 two, _T1 three) :one(one), two(two), three(three)
{
cout << "局部特化" << endl;
}
protected:
_T1 one;
_T1 two;
_T1 three;
};
//完全特化
template <> class A
{
public:
A(int one, int two, int three) :one(one), two(two), three(three)
{
cout << "完全特化" << endl;
}
protected:
int one;
int two;
int three;
};
void Test()
{
A a(1, 2, 3);
A b(1, "as", 1.22);
A c(1, 2, 1.22);//三个类型
A d("qew", "fasd", "fads");
}
int main()
{
Data data;
Data* object = new Data;
data.print();
object->print();
//两个不同类型中的count,不会因为一个类型中值的改变而另一个类型中的值改变
cout << Data::count << endl;
cout << Data::count << endl;
test1();
Test();
return 0;
}
稍微复杂一点的模板就是模板类与模板类的嵌套,本质不难,大家学会剥洋葱,学会用别名替换即可
#include
#include
using namespace std;
template class MM
{
public:
MM(_T1 one, _T2 two) :one(one), two(two) {}
void print() { cout << one << "\t" << two << endl; }
template friend ostream& operator<<(ostream& out,const MM<_T1, _T2>& object);
protected:
_T1 one;
_T2 two;
};
template ostream& operator<<(ostream& out,const MM<_T1, _T2>& object)
{
out << object.one << "\t" << object.two << endl;
return out;
}
template class Data
{
public:
Data(_T1 one,_T2 two):one(one),two(two){}
void print() { cout << one << "\t" << two << endl; }
template friend ostream& operator<<(ostream& out, const Data<_T1, _T2>& object);
protected:
_T1 one;
_T2 two;
};
template ostream& operator<<(ostream& out, const Data<_T1, _T2>& object)
{
out << object.one << "\t" << object.two << endl;
return out;
}
int main()
{
MM info(19, "king");
MM score(99, 88);
Data< MM, MM> king(info, score);
king.print();
using kk = Data< MM, MM>;
using kkk = MM;
Data data(king, info);
data.print();
return 0;
}