【C++】模板进阶,搞定泛型编程

一、模板的概念

模板概念:

  • 模板实现了通用类型的代码,不需要关心数据的类型,因此 C++标准模板库STL产生。模板可以分为:类模板和函数模板,其类型推导和具体代码生成都是在编译阶段。
    • 没有实例化的模板:编译器只是对模板进行简单的语法检测,并不会生成代码
    • 实例化之后:根据用户对模板实例化的类型来生成代码,并且对生成的代码进行语法检测

模板类型的参数:

  • 类型模板参数:类型不确定的,实例化后才生成对应代码
  • 非类型模板参数:类型已经具体化
    • 如果有缺省或者传参时,必须是常数,因为要在编译阶段确定大小
    • 浮点数、类对象以及字符串不允许作为非类型模板参数
template <class T, size_t N = 5>	// 非类型模板参数缺省时,必须是常数
class arr
{
   
public:
	arr()
		:_size(0)
	{
   }
	T& operator[](const int index){
   return _arr[index];}
	void insert(const T& data){
   _arr[_size++] = data;}
private:
	T _arr[N];
	size_t _size;
};
int main()
{
   
	arr<int, 10> a;	// 非类型模板参数传参时必须是常数,否则报错
	return 0;
}

模板的编译链接过程:

  • 有以下加法模板函数:函数声明:a.h头文件中,函数定义:a.cpp中
a.h头文件:加法模板的声明
#pragma once
template <class T>
T Add(const T& left, const T& right);

a.cpp源文件:加法模板的定义
#include "a.h"
template <class T>
T Add(const T& left, const T& right)
{
   
	return left + right;
}

main.cpp 
#include "a.h"
int main()
{
   
	int sum = Add(1, 2);
	return 0;
}

注意:这段代码在链接过程中会发生错误,找不到 int 类型的模板函数地址!

  • 原因:模板的分离编译,没有生成对应类型的代码,造成链接时找不到函数地址入口
    • 编译:对程序进行语法正误检测,检查无误后生成汇编代码。注意:头文件不参加编译,并且编译器对一个工程中的多个源文件是分离编译的。
    • 链接:将对个 .obj 目标文件合并成一个,并处理未解决符号表中的地址问题,到其他源文件的导出符号表中寻找对应函数地址。
  • 分离编译:同一项目有多个源文件共同实现,而每个源文件都是单独生成目标文件,最后才将所有文件链接起来形成单一的可执行文件。
    • a.cpp源文件在编译时,编译器没有看到对 Add 模板函数的实例化,因此不会生成具体的 int 类型代码
    • main.obj 目标文件在连接时,去其他目标文件找 Add< int >的函数地址,没有找到因此报连接错误。

解决:

  1. 在模板定义处显示实例化,不推荐
  2. 将模板声明和定义放到同一 .hpp 头文件中
1.在模板定义处显示实例化
#include "a.h"
template <class T>
T Add(const T& left, const T& right)
{
   
	return left + right;
}
void Test()
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值