第一类:函数模板
1.函数模板:函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计。
2.模板函数:在使用函数模板时,要将这个形参实例化为确定的数据类型。将类型形参实例化的参数称为模板实参;
用模板实参实例化的函数称为模板函数。模板函数的生成就是将函数模板的类型形参实例化的过程。
3.模板的实例化:模板的实例化指函数模板 生成模板函数 的过程。
4.模板的实参推演:
注意
1.不能产生二义性
2.保证有实参
5.模板的特例化(专用化):
当模板的逻辑不能满足特殊类型的需求,需要实现特例化:
1.完全特例化 或者叫 全特化: 例如: 函数模板 类模板
2.部分特例化 偏特化:
注意事项
特例化版本满足模板版本的逻辑
#include<iostream>
//普通的函数版本
bool Compare(char* cpa, char* cpb)
{
std::cout << "bool Compare(char*, char*)" << std::endl;
return strcmp(cpa, cpb) > 0;
}
//模板的版本
template<typename T>
bool Compare(T a, T b)
{
std::cout << "template<typename T> bool Compare(T,T)" << std::endl;
return a > b;
}
//模板特例化版本
template<>
bool Compare(char* a, char* b)
{
std::cout << "template<> bool Compare(char*, char*)" << std::endl;
return strcmp(a, b) > 0;
}
int main()
{
char* p = "hello";
char* q = "world";
Compare(p, q);
Compare<char*>("hello", "world");
int a = 10;
int b = 20;
Compare<int>(10,20);
return 0;
}
6.类型参数: template<class T> // T是类型模板参数
7.非类型参数: template<int val> //int val是非类型模板参数
1.常量
2.不允许浮点型
8.模板的重载 :
1.普通函数版本
2.模板的版本
3.模板的特例化版本
精确匹配时的优先级: 1 > 3 > 2
9.模板的默认值 : 传递+推演 ==》 实例化
函数模板的默认值 C++11特性
1.取传递的值
2.推演
3.默认值
且不必要从右向左依次赋予
//模板类型参数被赋默认值,且不必从右向左依次给默认值
template<typename F = int, typename S, typename T = int,typename R = float>
R Sum(F first, S second, T third)
{
return first + second + third;
}
int main()
{
auto rt = Sum<int>(10, 21.1, 15.5f);
std::cout << typeid(rt).name() << std::endl;
return 0;
}
10.模板来接收不明确类型的返回
auto 自适应调节类型
11.显示实例化
template
模板一般写在.h文件中
第二类:类模板
函数的模板的编译(这个特性的存在,所以在类中实现函数的时候需要测试每一个函数)
1.定义点 只编译模板头部
2.调用点 编译模板函数
模板类型参数列表中
typename/class 定义类型参数
1.类型参数
2.非类型参数
//一个代码
template<typename T>
class CLink
{
public:
template<typename E>
friend class CLink;
public:
CLink()
{
phead = new Node();
}
~CLink()
{
Node* pCur = phead;
Node* pBack = pCur;
while (pCur != NULL)
{
pBack = pCur->pnext;
delete pCur;
pCur = pBack;
}
phead = NULL;
}
//CLink(const CLink<T>& rhs); //只支持原来的类型
template<typename E> //用来支持由类似于 int->double的转换
CLink(const CLink<E>& rhs)
{
phead = new Node();
Node* pNewCur = phead;
CLink<E>::Node* pCur = rhs.phead->pnext;
while (pCur != NULL)
{
Node* pnewnode = new Node(pCur->mdata);
pNewCur->pnext = pnewnode;
pCur = pCur->pnext;
pNewCur = pNewCur->pnext;
}
}
void push_front(const T& val)
{
Node* pnewnode = new Node(val);
pnewnode->pnext = phead->pnext;
phead->pnext = pnewnode;
}
void Show()
{
Node* pCur = phead->pnext;
while (pCur != NULL)
{
std::cout << pCur->mdata << " ";
pCur = pCur->pnext;
}
std::cout << std::endl;
}
class Node; //Node* find(const T& val)用到了Node这个类,在前面要声明Node这个类
Node* find(const T& val)
{
Node* pCur = phead->pnext;
while (pCur != NULL)
{
if (pCur->mdata == val)
{
return pCur;
}
pCur = pCur->pnext;
}
return NULL;
}
private:
class Node
{
public:
Node(T val = T()) :mdata(val), pnext(NULL){};
public:
T mdata;
Node* pnext;
};
Node* phead;
};
//template<typename T>
//typename CLink<T>::Node* CLink<T>::find(const T& val) //typename 说明这个 CLink<T>::Node* 是一个类型
//{
// Node* pCur = phead->pnext;
// while (pCur != NULL)
// {
// if (pCur->mdata == val)
// {
// return pCur;
// }
// pCur = pCur->pnext;
// }
// return NULL;
//}
int main()
{
CLink<int> ilink;
CLink<double> dlink(ilink);
CLink<int> ilink2(ilink);
return 0;
}
template<typename T1,
typename T2>
class Sum
{
public:
Sum(T1 f, T2 s) :first_arg(f), second_arg(s){}
T2 add()
{
return first_arg + second_arg;
}
template<typename R>
R add()
{
return first_arg + second_arg;
}
template<>
char* add<char*>()
{
char arr[1000] = { '\0' };
std::cout << "Sum<char*,char*>" << std::endl;
strcat(arr, first_arg);
strcat(arr, second_arg);
return arr;
}
private:
T1 first_arg;
T2 second_arg;
};
/*
全特化
*/
template<>
class Sum<char*,char*>
{
public:
Sum(char* f, char* s) :first_arg(f), second_arg(s){}
char* add()
{
char arr[1000] = { '\0'};
std::cout << "Sum<char*,char*>" << std::endl;
//char* ptmp = new char[strlen(first_arg) + strlen(second_arg) + 1]();
strcat(arr, first_arg);
strcat(arr, second_arg);
return arr;
}
private:
char* first_arg;
char* second_arg;
};
/*
偏特化
*/
template<typename T1,
typename T2>
class Sum<T1*, T2*>
{
public:
Sum(T1* f, T2* s) :first_arg(f), second_arg(s){}
T2 add()
{
std::cout << "template<T1,T2> class Sum<T1*,T2*>" << std::endl;
return *first_arg + *second_arg;
}
private:
T1* first_arg;
T2* second_arg;
};
int main()
{
Sum<int, float> mysum(10, 20.1);
float rt = mysum.add();
std::cout << rt << std::endl;
Sum<char*, char*> mysum1("hello", "world");
char* rt1 = mysum1.add<char*>();
std::cout << rt1 << std::endl;
return 0;
}