模板定义:模板就是实现代码重用机制的一种工具,他可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码可重用性。
模板可以分为两类:一个是函数模板,一个是类模板
大白话:C++是一门强类型语言,编写一段通用的逻辑,可以把任意类型的变量传进去处理,通过通用逻辑设计为模板,摆脱了类型的
限制,极大地提升了代码的可重用性。
模板实例化:模板定义本身不参与编译,而是编译器根据模板的用户使用模板提供的类型参数生成代码,再进行编译。用户提供不同的
类型参数,就会实例化处不同的代码。
类模板描述了一组相关的类或数据类型,他们只能通过类型来区分:整数值、指向(或引用)具有全局链接的变量的指针、其他组合。
类模板尤其适用于描述通用但类型安全的数据结构。
类模板的使用:
template <类型形式参数>
class 类名
{
//类声明体
};
template <类型形式参数>
返回类型 类名 <类型>::成员函数名1(形参)
{
//成员函数定义体
}
. . .
template <类型形式参数>
返回类型 类名 <类型>::成员函数名N(形参)
{
//成员函数定义体
}
#include <iostream>
using namespace std;
template <class T>
class Compare
{
public:
bool myequal(T a, T b);
};
template <class T>
bool Compare<T>::myequal(T a, T b)
{
return a == b;
}
/*
类模板全特化
所谓模板全特化限定死模板实现的具体类型
*/
template <>
class Compare<float>
{
public:
bool myequal(float a, float b);
};
bool Compare<float>::myequal(float a, float b)
{
return std::abs(a - b) < 0.001;
}
int main01()
{
Compare<int> C;
bool res = C.myequal(1, 1);
Compare<float> C2;
bool res2 = C2.myequal(1.001, 1.005);
if (res)
cout << "==" << endl;
else
cout << "!= " << endl;
if (res2)
cout << "2: ==" << endl;
else
cout << "2: != " << endl;
return 0;
}
/*
模板偏特化
偏特化是指提供另一份template定义式,而其本身仍为 templatized ,这是针对于 template 参数更进一步的条件限制所设计出来的一个特化版本
也就是说如果有多个类型,那么只限定其中的一部分
*/
template <class T1, class T2>
class Test
{
public:
Test(T1 a, T2 b) :_a(a), _b(b)
{
cout << "模板化" << endl;
}
private:
T1 _a;
T2 _b;
};
//模板全特化
template <>
class Test<int, int>
{
public:
Test(int a, int b) :_a(a), _b(b)
{
cout << "模板全特化" << endl;
}
private:
int _a;
int _b;
};
//模板偏特化
template <class T>
class Test<int, T>
{
public:
Test(int a, T b):_c(a), _d(b)
{
cout << "模板偏特化" << endl;
}
private:
int _c;
T _d;
};
int main02()
{
Test<double, double> t1(1.01, 1.01);
Test<int, int> t2(1, 1);
char arr[] = "111";
Test<int, char*> t3(2, arr);
return 0;
}
函数模板
函数模板一般定义:
template <类型形式参数> //类型形式参数即此格式:<typename 形参> 或 <class 形参>
返回类型 函数名(形参)
{
//函数定义体
}
//普通模板函数
template <class T1, class T2>
bool compare(T1 a, T2 b)
{
cout << "普通模板" << endl;
return a == b;
}
//函数模板特化
//函数模板特化和类模板特化本质是一样的,是对模板参数的特殊处理:
template<>
bool compare(const char* a, const char* b)
{
cout << "函数模板特化" << endl;
return strcmp(a, b) == 0;
}
int main()
{
cout << compare(1, 2) << endl;
cout << compare("ab", "ab") << endl;
}
总结:
1.函数模板只有特化,没有偏特化
2.模板、模板的特化和模板的偏特化都存在的情况下,编译器在编译阶段进行匹配,优先特殊的。
3.模板函数不能是虚函数;因为每个包含虚函数的类具有一个 virtual table, 包含该类的所有虚函数的地址,
因此 vtable 的大小是确定的。模板只有被使用时才被实例化,将其声明为虚函数会使 vtable 的大小不确定。
所以,成员函数模板不能为虚函数。