目录
一,函数模板
函数模板格式
模板函数的原理
模板匹配原则
二,类模板
类模板格式
类模板实例化
函数重载劣势:
- 如重载函数仅为类型不同,代码复用率较低,新类型就要增加对应函数;
- 代码可维护性较低,一个出错可能所有重载均出错;
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段,模板是泛型编程的基础;
模板:函数模板、类模板;
VS编译器模板不可在函数内部定义,类似命名空间;
一,函数模板
函数模板代表了一个函数的家族,该函数模板与函数数据类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本;
函数模板格式
template
返回值类型 + 函数名 + (参数列表) { }
template
void Swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
模板函数的原理
函数模板是一个蓝图,本身并不是函数,是编译器用使用方式产生特定具体类型的模具,所以其实模板就是将本来应该重复做的事交给了编译器;
在编译器编译的阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用,即,当double类型使用模板函数时,编译器通过对实参类型的推演,将T确定为double,然后产生一份专门处理double类型的代码;
注:内置类型变量初始化方式
//以下三种方式效果相同 int a=1; //直接赋值 int a(1); //括号初始化 int a{1}; //花括号初始化,C++11引入 int a(); //编译器会解析为函数声明
函数模板的实例化
template
void Swap(T x,T y)
{
T tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 1;
double b = 2;
//显示实例化
Swap(a, b); //或Swap(a, (int)b);
return 0;
}
注:如函数模板中的函数形参中没有用模板参数T,函数体内有用,此时无法通过参数推演T的类型,只能显示实例化;
class A
{
public:
A(int a = 10)
:_a(a)
{}
private:
int _a;
};
template
T fun(int x)
{
T a(x);
return a;
}
int main()
{
//只能显示实例化
A a = fun(1);
return 0;
}
模板匹配原则
注:
template
void Swap(T x,T y)
{
T tmp = x;
x = y;
y = tmp;
}
void Swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 1;
int b = 2;
Swap(a, b); //调用void Swap(int x, int y)
return 0;
}
template
void Swap(T1 x,T2 y)
{
T1 tmp = x;
x = y;
y = tmp;
}
void Swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
Swap(1, 2); //使用void Swap(int x, int y)
Swap(1, 2.0); //使用void Swap(T1 x,T2 y)
return 0;
}
二,类模板
类模板格式
template
class + 类模板名 { }
template
class stack
{
private:
T* _a;
int _size;
int _capacity;
};
类模板实例化
注:
template
class stack
{
private:
T* _a;
int _size;
int _capacity;
};
int main()
{
//需显示实例化
stackst1;
stackst2;
return 0;
}
template
class stack
{
public:
stack(int capacity = 4)
:_a(new T[capacity])
,_top(0)
,_capacity(capacity)
{}
~stack()
{
delete[] _a;
_a = nullptr;
_top = _capacity = 0;
}
//类内声明,类外定义
void push(const T& x);
private:
T* _a;
int _top;
int _capacity;
};
//类外定义,需加模板参数列表
template
void stack::push(const T& x)
{
_a[_top] = x;
_top++;
}
int main()
{
stackst1;
stackst2;
st1.push(1);
st2.push(1.1);
return 0;
}
注:函数模板和类模板都不支持在.h内声明,.cpp内定义,否则会链接错误;