目录
一、泛型编程
void Swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
void Swap(double& a, double& b)
{
double tmp = a;
a = b;
b = tmp;
}
void Swap(char& a, char& b)
{
char tmp = a;
a = b;
b = tmp;
}
对于这段代码来说,仅实现一个功能却重载了好几次,这样的代码耦合性太强,维护起来比较麻烦,面对这样的问题C++之父就创造了模板,
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础
二、模板
1.函数模板
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
template<typename T>//这里typename可以用class替换
void func(T x)
{
//...
//
//...
}
2.类型推理与实例化
函数模板类似一张图纸,它本身并不是函数,是编译器会根据函数调用时候传递的参数类型进行推导,找到最匹配的模板参数类型。
汇编代码中编译器调用的Swap函数不是同一个
3.匹配原则
当编译器进行模板参数匹配时,它会优先考虑完全匹配的情况。如果有一个非模板函数,而且该函数模板还能被实例化成这个非模板函数的话,这时候编译器就不需要特化模板。
template<class T1, class T2>
T1 Add(T1 a, T2 b)
{
std::cout << "T Add()" << std::endl;
return a + b;
}
int Add(int a, int b)
{
std::cout << "int Add()" << std::endl;
return a + b;
}
int main()
{
Add(1, 2); //非模板函数完全匹配,不需特化
Add<int>(1, 2); //指定调用模板函数
Add(1, 1.2); //模板函数可以生成更加匹配的版本
return 0;
}
三、类模板
1.类模板的定义
template<typename T>
class ClassName
{
// 类成员和方法
};
在模拟实现栈的时候有了模板便十分方便
template<class T>
class Stack
{
public:
Stack()
{
//...
}
//...
void push_back(const T& val)
{
//...
}
//...
private:
T _arr;
int _size;
int _capacity;
};
int main()
{
Stack<int> st_i; //整型
st_i.push_back(1);
st_i.push_back(2);
Stack<double> st_d; //浮点型
st_d.push_back(1.1);
st_d.push_back(1.2);
}
类模板不像函数模板那样可以自动识别类型,大多时候都需要程序员显示调用。