模板的特性1:需要遵守约定
模板将类型以一个标识符替代,想要使用模板就需要遵守模板对这个标识符的要求,比如对标识符有什么成员变量以及成员函数。
#include <iostream>
#include <vector>
using namespace::std;
//*****************这是一个模板类的实现,展示模板的特性之一:约定性*******************************
template<class T> class X
{
public:
typename T::id i; //约定类型T中有id这个类型,并且创建一个id类型的变量,typename是关键字,用typename 告诉编译器T::id是一个类型标识符
public:
void f() {
i.g(); //约定i中有g()这个函数
}
};
class Y
{
public:
class id
{
public:
void g() {
cout << "this is the Y::id object function g()" << endl;
}
};
};
/*
int main() {
X<Y> xy;
xy.f();
}
*/
模板类型的模板参数
//********************************这是一个模板类型的模板参数案例****************************
template <class T, template <class> class Seq> //T是一个类型,Seq是一个模板类型,这个模板类型有一个参数(无需写出参数名)
class Container
{
public:
Seq<T> seq; //Seq模板类型中的类型参数是T
public:
void printSeq() {
cout << "the size of seq : " << seq.size() << endl;
}
void push_back(T t)
{
seq.push_back(t);
}
};
template<class T> class Vec
{
public:
vector<T> vec;
public:
void push_back(T t)
{
vec.push_back(t);
}
size_t size() {
return vec.size();
}
};
/*
int main()
{
Container<int, Vec> cv;
cv.push_back(1);
cv.push_back(2);
cv.printSeq();
}
*/
函数成员模板和类成员模板
//***********************成员函数中的模板:分为函数成员模板和类成员模板*********************************
template <class T> class com
{
public:
T t;
com(const T& tt) :t(tt){
std::cout << "t : " << t << endl;
}
template <class U> com(const com<U>& u) : t(u.t) //成员函数模板
{
std::cout << "u : " << t << endl;
}
};
template <class T> class outer
{
public:
template<class R> class iner //成员函数类
{
public:
//template<class T> template<class R>
void f()
{
std::cout << "out " << typeid(T).name() << endl;
std::cout << "inner " << typeid(R).name() << endl;
std::cout << "this " << typeid(*this).name() << endl;
}
};
};
/*
int main() {
com<float> a(1);
com<double> b(a);
outer<float>::iner<int> ou;
ou.f();
outer<float>::iner<int> oc(ou); //这里会调用拷贝构造函数
}
*/
模板特化以及模板重载
在实例化模板时,优先考虑特化程度高的模板,比如有指针修饰符修饰的模板或者直接特化的模板,若特化程度高的模板可以匹配就使用特化程度高的模板,当然匹配度是更重要的指标。
//*****************模板特化以及模板重载************************************
#include<stack>
template <class StackType>
void emptyTheStack(StackType& stk)
{
cout << "this is stackType" << endl;
}
template <class StackType>
void emptyTheStack(stack<StackType*> & stk) //经过指针特化的模板,当实例化为参数为指针时优先调用此模板
{
cout << "this is stack<StackType*>" << endl;
}
template<>
void emptyTheStack(float& stk) //直接float 类型,显示特化
{
cout << "this is float& stk" << endl;
}
void emptyTheStack(int stk) //重载模板函数
{
cout << "this is int stk" << endl;
}
int main()
{
double a = 1;
emptyTheStack(a); //调用第一个模板
float b = 1;
emptyTheStack(b);//调用第三个模板
stack<float*> c;
emptyTheStack(c); //调用第二个模板
int d = 1;
emptyTheStack(d);//调用最后一个重载函数
}
模板中的符号解析
如果符号定义涉及到未确定类型,在编译的第一阶段只会在已经定义的符号表中查找该符号,不会到不确定类型中查找该符号。
//********************************关联不确定类型标识符的编译*************************
#include<algorithm>
#include<typeinfo>
using std::cout;
using std::endl;
void g() { cout << "global g()" << endl; } //全局定义
template <class T> class YY
{
public :
void g()
{
cout << "Y<" << typeid(T).name() << ">::g()" << endl;
}
void h()
{
cout << "Y<" << typeid(T).name() << ">::h()" << endl;
}
typedef int E; //局部定义
};
typedef double E; //全局定义
//一个全局定义的模板函数
template<class T> void swap(T& t1, T& t2)
{
cout << "global swap" << endl;
T temp = t1;
t1 = t2;
t2 = temp;
}
template<class T> class XX :public YY<T>
{
public:
E f() //E的返回类型是double
{
g(); //这个会编译成全局函数,而不是YY中的函数定义体,因为YY中的函数定义体是关联未定类型的,不会优先编译
this->h();//这是YY中的
T t1 = T(0);
T t2 = T(1);
cout << "t1: " << t1 << endl;
cout << "t2: " << t2 << endl;
swap(t1, t2);
std::swap(t1, t2);
cout << "E type: " << typeid(E).name() << endl;
return E(t2);
}
};
int main()
{
XX<int> x;
cout << x.f() << endl;
}