泛型编程
- 泛型编程是指编写跟类型无关的代码,它是代码复用的一种手段。模板是泛型编程的基础。
- 模板又分为函数模板和类模板。
函数模板
函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
template<typename T>
void Swap(T& left, T& right)
{
T tmp = left;
left = right;
right = tmp;
}
int main()
{
int a = 10, b = 20;
char c = 1, d = 2;
Swap(a, b);
Swap(c, d);
cout << a << " " << b << endl;
cout << c << " " << d << endl;
system("pause");
return 0;
}
- 模板是一个模具,它是将本来应该我们重复做的事情交给了编译器 在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。
模板实例化
- 编译器通过对实参类型的推演,生成具体代码的过程就叫做模板的实例化。
隐式实例化
- 让编译器根据实参推演模板参数的实际类型
template<class T>
Add(const T& left, const T& right)
{
return left + right;
}
int main()
{
int a = 10, b = 20;
double c = 1.0, d = 2.0;
Add(a, b);//调的是Add(int,int)
Add(c, d);//调的是Add(double,double)
system("pause");
return 0;
}
显示实例化
- 在函数名后的<>中指定模板参数的实际类型
template<class T>
Add(const T& left, const T& right)
{
return left + right;
}
int main()
{
int a = 10, b = 20;
double c = 1.0, d = 2.0;
Add(a, b);//隐式实例化
Add<double>(a, d);//显示实例化
system("pause");
return 0;
}
函数模板的匹配规则
函数模板的匹配原则是:如果显示的指定模板,那就使用模板去调,如果没有指定,那就优先调现成的函数接口。
类模板
#include <iostream>
#include <assert.h>
using namespace std;
template<class T>
class Vector
{
public:
Vector(size_t capacity=10)
:_array(new T[capacity])
, _capacity(capacity)
, _size(0)
{}
void PushBack(const T& x)
{
_array[_size] = x;
_size++;
}
~Vector()
{
delete[] _array;
_array = nullptr;
_capacity = _size = 0;
}
int Size()
{
return _size;
}
int Size()const
{
return _size;
}
T& operator[](size_t pos)
{
assert(pos < _size);
return _array[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < _size);
return _array[pos];
}
private:
T* _array;
size_t _capacity;
size_t _size;
};
void PrintVector(const Vector<int>& v)//当传的是const对象时,调的函数也必须是const的
{
for (size_t i = 0; i < v.Size(); i++)
{
cout << v[i] << " ";
}
}
int main()
{
Vector<int> v;
v.PushBack(1);
v.PushBack(2);
v.PushBack(3);
for (size_t i = 0; i < v.Size(); i++)
{
v[i] *= 2;
cout << v[i]<< " ";
}
cout << endl;
Vector<char> v1;
v1.PushBack('a');
v1.PushBack('b');
v1.PushBack('c');
for (size_t i = 0; i < v1.Size(); i++)
{
v1[i] *= 2;
cout << v1[i] << " ";
}
system("pause");
return 0;
}
当我们在类里面声明,类外定义的时候,应该在最前面加上模板参数:
template<class T>
Vector<T>::Vector(size_t capacity = 10)
:_array(new T[capacity])
, _capacity(capacity)
, _size(0)
{}
需要注意的的是,在类和对象中:
Vector//是类型
而在模板中:
Vector//是类名
Vector<int>//是类型