C++_模板初阶

在面向对象中,我们可以使用重载来实现多态。

但是问题在于,重载的函数仅仅是类型不同,代码复用率比较低,只要有新的类型出现时,就要增加对应的函数;另一方面它的代码可维护性比较低,一个出错可能所有的重载均出错。

那么在C++中,我们可以使用模板来尽量避免这些问题。

一、函数模板

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

函数模板格式如下:

template<typename T1, typename T2,......,typename Tn>

返回值类型 函数名(参数列表){}

其中,typename是用来定义模板参数关键字,也可以使用class。

要注意模板和函数之间是不需要任何符号的,并且它们可以在同一行。

下面的代码就是使用函数模板的一个实例:

cpp 复制代码
template <typename T>
void Swap(T& left,T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

函数模板本身不是一个函数,而是"蓝图",是编译器用使用方式产生特定具体类型函数的模具。

模板就是将本来应该我们做的重复的事情交给了编译器。

当使用了模板时,在编译器编译阶段,编译器需要根据传入的实参类型来推演生成对应的函数,然后供调用。

假如我们用double类型使用函数模板时,编译器通过对实参类型的推演,确定T为double,然后生成专门处理double类型参数的函数:

可以看到,类型仍然为double,变量的值也被成功交换。

实例化函数模板的方式有两种,一种是隐式实例化,另一种是显式实例化。

隐式实例化,即让编译器根据实参推演推演模板参数的实际类型,例如:

从监视1窗口可以看到,得到了正确的结果。

那么,根据刚才的Add函数模板及变量,能否这样隐式实例化呢?

cpp 复制代码
Add(num0,num2);

根据编译器警告信息,可以明确是不可行的:

要处理这种状况,方法有两种,一种是用户自己强制类型转换:

cpp 复制代码
Add((double)num0, num2);
Add(num0, (int)num2);

还有一种方法就是,显式实例化。

只需要在函数名后的<>中指定模板参数的实际类型即可显式实例化:

如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

模板参数的匹配规则如下:

  1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数;

  2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板;

3.模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。

例如,func同时是函数,也是模板。现在在main函数中用不同的类型对其实例化,根据打印输出结果可知,当参数为int时,调用的是函数,当参数不为int时,调用的是根据模板生成的函数:

二、类模板

类模板是编译器根据被实例化的类型生成具体类的模具。

在STL中,如vector,随处可见类模板的身影:

类模板的定义格式如下:

template <class T1, class T2, ..., class Tn>

class 类模板名

{

// 类内成员定义

};

与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>

中即可。

类模板名字不是真正的类,实例化的结果才是真正的类。

一个类模板实例化的具体例子:

相关推荐
不过普通话一乙不改名1 小时前
第四章:并发编程的基石与高级模式之Select语句与多路复用
开发语言·golang
ningqw1 小时前
JWT 的使用
java·后端·springboot
追逐时光者1 小时前
精选 2 款 .NET 开源、实用的缓存框架,帮助开发者更轻松地处理系统缓存!
后端·.net
JCBP_2 小时前
QT(1)
开发语言·汇编·c++·qt
可峰科技2 小时前
qt配置ros2环境,简单版本
开发语言·qt
David爱编程2 小时前
指令重排与内存屏障:并发语义的隐形守护者
java·后端
郝学胜-神的一滴2 小时前
C++ Core Guidelines 核心理念
开发语言·c++·设计模式·代码规范
朱砂绛2 小时前
【大模型本地运行与部署框架】Ollama的API交互
开发语言·lua·交互
胡gh3 小时前
数组开会:splice说它要动刀,map说它只想看看。
javascript·后端·面试
Pure_Eyes3 小时前
go 常见面试题
开发语言·后端·golang