【C++初阶】模板初阶
前言
在我们之前的学习中我们要实现一个交换函数,会这么写
//void Swap(int* x,int* y)
void Swap(int& x,int& y)
{
int tmp = x;
x = y;
y = tmp;
}
这个函数可以实现int类型的变量进行交换,但要实现其他类型,如:double、float……等,便要使用函数重载,每当出现新的类型时就需要写一个新的对应函数,太麻烦了!
哪有什么方法可以只用一个函数就可以实现都种不同类型变量进行交换呢?
泛型编程就可以解决这种问题!!!
泛型编程
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段,模板是泛型编程的基础
它就是给编译器一个模具,不同的类型变量就相当于是不同的材料,以此来获得不同的铸件
它的本质就是把分辨类型的工作交给编译器
模板
模板分为:函数模板和类模板
函数模板
概念:
函数模板是一个函数家族,与变量类型无关,在使用时根据实参类型生成特定类型版本
格式:
template<typename T1, typename T2,……>
返回类型 函数名(参数列表)
{}
注:typename也可以用class代替
template<typename T>
void Swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
int main()
{
int x = 1, y = 2;
Swap(x, y);
cout << x << " " << y << endl;
double m = 1.01, n = 2.02;
Swap(m, n);
cout << m << " " << n << endl;
return 0;
}
原理:
函数模板的工作实质是将原本需要我们重复去做的事交给编译器去做,编译器根据传入实参类型来生成对应类型的函数
实例化:
不同类型参数使用函数模板被称为函数模板的实例化,实例化分为:隐式实例化和显式实例化
1、隐式实例化:
template<typename T>
void Swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
int main()
{
int x = 1, y = 2;
Swap(x, y);
cout << x << " " << y << endl;
double m = 1.01, n = 2.02;
Swap(m, n);
cout << m << " " << n << endl;
return 0;
}
2、显式实例化:
当进行不同类型变量间的类型转换时,隐式实例化就无法实现了,因为在模板中编译器一般不会自动进行类型转换,这时就可以使用显式实例化和强制类型转换
template<typename T>
T Add(const T& a, const T& b)
{
return a + b;
}
int main()
{
int x = 1, y = 2;
double m = 1.01, n = 2.02;
//强制转换
cout << Add(x, (int)m) << endl;
cout << Add((double)x, m) << endl;
//显式实例化
cout <<Add<int>(x, n) << endl;
cout <<Add<double>(x, n) << endl;
return 0;
}
匹配规则
1、在有非模板函数和同名模板函数时,编译器会优先使用非模板函数
2、对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而
不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数,那么将选择模板
类模板
格式:
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
template<class T>
class Stack
{
public:
Stack(size_t capacity = 4)
{
_a = new T[capacity];
_capacity = capacity;
_top = 0;
}
void push(const T& x)
{
if (_top >= _capacity)
{
/*_a = (T*)malloc(sizeof(T) * n);
if (nullptr == _a)
{
perror("malloc申请空间失败");
return;
}*/
int newcapacity = _capacity * 2;
T* tmp = new T[newcapacity];
delete[] _a;
memcpy(tmp, _a, sizeof(T) * _top);
_capacity = newcapacity;
}
_a[_top++] = x;
}
private:
T* _a;
size_t _capacity;
size_t _top;
};
实例化:
类模板实例化和函数模板实例化不一样,它需要在类模板名后面加<>,然后将实例化类型放在<>中,类模板名字不是真正的类,而实例化的结果才是真正的类
Stack<int> s1;