【C++笔记】模板进阶

一、非类型模板参数

我们之前学过的模板虽然能很好地帮我们实现泛型编程,比如我们可以让一个栈存储int类型的数据,一个栈存储double类型的数据:

template <class T>
class Stack {
public :
	Stack() {
		cout << "Stack()" << endl;
	}
	~Stack() {
		cout << "~Stack()" << endl;
	}
private :
	T* _data;
}

int main() {
	Stack<int> st1;
	Stack<double> st2;
	return 0;
}

但是如果我们想实现两个静态的栈,一个容量为10,另个一容量为100,那就没有办法了。

对此,C++又引入了一个非类型模板参数

template <class T, size_t N>
class Stack {
public:
	Stack() {
		cout << "Stack()" << endl;
	}
	~Stack() {
		cout << "~Stack()" << endl;
	}
private:
	T data[N];
}

这样我们就可以在实例化的时候给上对应的容量了:

int main() {
	Stack<int, 10> st1;
	Stack<double, 100> st2;
	return 0;
}

需要注意的是
非类型模板参数一定要是常量,不能是变量:
在这里插入图片描述
非类型模板参数一定要是整型(包括整型家族的所有成员char、short……):
在这里插入图片描述
直到C++20版本才引入。

二、类模板的特化

模板的特化就是针对某些类型进行特殊化处理。
比如我们现在随便写一个类模板:
在这里插入图片描述
如果我们想针对两个参数一个是int一个是double的这种情况特殊处理,让它输出不同的内容就可以使用特化:
在这里插入图片描述
上面的这种叫做全特化,与之对应的还有偏特化:
在这里插入图片描述
在匹配的时候也是遵循最匹配原则,看哪个最符合条件就匹配哪个。

而且在特化的时候也并不需要写的很具体,其实也可以像下面这样写:
在这里插入图片描述

特化必须要有原模板,也就是最初的没有任何特化的模板。

三、模板的分离编译

模板其实是不支持分离编译的,即声明和定义分离(声明在一个文件,定义在另个文件)。
在这里插入图片描述
在这里插入图片描述
这样做的话会发生连接错误:
在这里插入图片描述

而我们若是讲一个普通函数分离编译就没问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这其中的原因是因为函数模板比普通函数多了一个步骤:实例化,因为函数模板其实和具体函数其实是一个一对多的关系,一个函数模板可以实例化出很多个功能相近但参数和返回值类型不同的函数。
也就是说我们在Stack.cpp中所写的可以比作一个骨架,从中只能得到这个函数的实现逻辑,所以在编译Stack.cpp的时候并不能生成具体的函数地址,这样main函数在调用的时候就自然找不到了。

解决这个问题的其中一种方法就是显示实例化:
在这里插入图片描述
在这里插入图片描述

但这种方法并不是一种很好的方法,因为它每一次只能解决一种类型,而且每一种类型都得要显示声明一次,这会是代码用于。

还有一种方法就是直接将声明和定义放在同一个文件里:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林先生-1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值