当前位置: 首页 > news >正文

C++模板初阶 -- 讲解超详细

目录

1.泛型编程

2. 函数模板

2.1 函数模板的概念

2.2 函数模板格式

2.3 函数模板原理

2.4 函数模板的实例化

2.5 模板参数的匹配原则

3. 类模板

3.1 类模板的格式

3.2 类模板实例化

3.3 模板分离


1.泛型编程

我们在理解泛型编程之前,先来看一个例子:

int add(int x, int y)
{return x + y;
}double add(double x, double y)
{return x + y;
}int main()
{cout << add(1, 2) << endl;cout << add(6.6, 2.5) << endl;return 0;
}

这个时候就很烦,如果每次实现两个数相加,不同于以上类型那我岂不是每次都要写一个重载函数?有没有一个办法能解决这个问题?能不能让编译器自动识别类型并计算结果?

这个时候C++就提出了泛型编程,什么是泛型编程?

简单理解:就相当一个模具,我们需要什么类型的物品就使用什么模具,在程序中就是当我们要传不同的参数,编译器可以套模板自动完成加减。(官方解释:泛型编程 - 编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。)

在C++中模板分为两种,一种是函数模板,一类是类模板!!!

2. 函数模板

刚刚了解了泛型编程,在此基础上又知晓了模板,那如何去使用模板?

2.1 函数模板的概念

函数模板:自动识别参数的类型,生成对应版本的函数,并计算对应的结果。

2.2 函数模板格式

template<typename T1, typename T2,......,typename Tn>模板        函数类型
template<class T1, class T2,......,class Tn>

注意:class和typename是关键字,二者都是可以用;但是不能用struct代替class(语法规定)

struct在C语言是结构体,在C++中升级为类(既可以是结构体,也可以是类);为了避免搞混,模板使用typename和class。(而typename和class也是有区别的,如果类模板实例化函数使用过程如果对模板的依赖性比较强,必须是用typename;其他情况二者都可以使用)(这里不是很好解释,后面写完几个容器时再解释)

template<class T>
const T& add(const T& x, const T& y)
{return x + y;
}int main()
{cout << add(1, 2) << endl;cout << add(6.6, 2.5) << endl;return 0;
}

2.3 函数模板原理

那这时如果两个参数不一样咋办?欸,编译器就会报错,还能咋办?!

只有一个模板参数T,传int和double,那我该是int还是double?编译器cpu干爆了都想不出来,那直接报错。

那这个咋解决?很简单啊,1个不行,那传2个模板T不就解决了!

template<class T1, class T2>
const T2& add(const T1& x, const T2& y)
{return x + y;
}int main()
{cout << add(1, 2) << endl;cout << add(6.6, 2.5) << endl;cout << add(6, 1.1) << endl;return 0;
}

总结:在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用

2.4 函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化 和显式实例化。

(1)隐式实例化:编译器自己根据数据推导。

template<class T>
const T& add(const T& x, const T& y)
{return x + y;
}int main()
{cout << add(1, 2) << endl;//编译器将1和2推导为intcout << add(6.6, 2.5) << endl;//编译器将6.6和2.5推导为doublereturn 0;
}

同时像刚才那样两个参数类型不同怎么办?

方法:(1)用户强制转化类型;(2)增加模板参数;(3)显示实例化

int main()
{cout << add(6, (int)1.1) << endl;cout << add((double)6, 1.1) << endl;return 0;
}

(2)显示实例化:在函数名后的<>中指定模板参数的实际类型

int main()
{cout << add<double>(6, 1.1) << endl; //7.1cout << add<int>(6, 1.1) << endl; //7return 0;
}

2.5 模板参数的匹配原则

(1)当非模板函数和模板函数同时存在时,函数模板也可以实例化为该函数。

//现成函数
void swap(int x, int y)
{int tmp = x;x = y;y = tmp;
}template<class T>
void swap(T x,T y)
{T tmp = x;x = y;y = tmp;
}int main()
{int a = 10;int b = 50;swap(a, b);//调用第一个swap<int>(a,b);//调用模板函数return 0;
}

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

// 现成函数
int add(int x, int y)
{return x + y;
}template<class T1,class T2>
T2 add(T1 x, T2 y)
{return x + y;
}int main()
{int a = 10;int b = 100;double c = 50;add(a, b);//吃现成,调用第一个函数add(a, c);//没有现成,套模板return 0;
}

3. 类模板

3.1 类模板的格式

template<class T1, class T2, ..., class Tn> 
class 类模板名
{// 类内成员定义
};  

在类模板里面我们常用关键字class,那类模板是如何使用的呢?请看下面:

template <class T>
class stack
{
public:stack(size_t capacity = 4):_size(0),_capacity(capacity)//,_arr(new T[_capacity]) //注意这里是按照声明顺序初始化{_arr = new T[_capacity];}
private:T* _arr;size_t _size;size_t _capacity;
};

这里只是对类模板的一些初步认识,在后面的容器会不断的使用类模板。

那这时类模板的调用是否是和普通函数一样? -- 答案是否定的

那类模板为什么不能根据数据自动推到类型实例化成合适的函数?

这个是由语法规定的,类模板实例化对T的依赖性比较高。

3.2 类模板实例化

类模板实例化和函数模板实例化是有区别的:

(1)函数模板实例化,会根据类型自动推导类型实例化;

(2)类模板实例化,由语法规定:类名+<T>才是类型。

在类里面,类名可以作为类型;

在类模板里面,类名+<T>才是类型。(必须+<T>,因为传参过程中形参不涉及T,但是实现过程用到了T)

int main()
{date<int> d1(2024, 9, 1);stack<int> s1(20);return 0;
}

3.3 模板分离

这里提一下:普通函数声明定义分离是可以的,但是模板函数和类是不支持分别定义在.h和.cpp文件的,会出现链接错误,至于为什么?就涉及到预处理,编译,汇编和链接这几个阶段了。

我们先简单了解一下;

预处理阶段展开头文件,宏替换,条件编译和去注释
编译阶段检查语法错误,生成汇编代码
汇编阶段

生成机器可以读懂的二进制汇编指令

链接阶段合并生成可执行文件,链接函数地址

在类和对象中的时候我们已经了解了call指令

基于此函数距离编译还差一个实例化<T>,这个T只有.cpp知道,但是每个文件又是单向操作,我在编译的时候是不知道的,但是编译时头文件:就是告诉编译器,你不用管待会儿给你,你先运行,但是链接的时候我去找编译器要,欸没有,这不是欺诈吗?所以就会出现链接错误。

举个通俗易懂的例子:

类模板这里只是初步的了解,后面会更加深入的学习。

http://www.dtcms.com/a/466523.html

相关文章:

  • 网站免费优化工具广州做网站公司排名
  • 以太网PHY收发器深度解析:从基础原理到选型实践
  • 哪个网站微博做的最好济南网络推广网络营销
  • 做那种类型的网站seo好湘潭网站建设 排名磐石网络
  • 四川平台网站建设方案哪个网站可以做全网推广
  • 网站安全防黑联盟广州网站开发公司哪家好
  • 实验室烧杯的种类与选择,不同材质的实验室烧杯有何优缺点?
  • 公司怎么建立网站吗新闻页面设计
  • Linux学习笔记--获取输入设备信息
  • 【Python+GEE】遥感数据计算、分析和可视化及森林监测、洪涝灾害、干旱评估、植被变化等案例
  • 基础搭建图形化编程:课程目录介绍 总纲
  • 【时时三省】(C语言基础)顺序读写数据文件
  • wordpress搬站深圳企业网站制作哪个
  • 专门做酒店的招聘网站做实验的网站
  • 行业门户网站设计开网站需要什么流程
  • 抗辐照MCU芯片在低轨商业卫星原子钟中的适配与优化
  • 成都市分类信息网站开发淘宝网页制作
  • 攻防世界-Web-easytornado
  • 溧阳市城乡建设局网站鄢陵网站建设电脑建站
  • Linux-db2look创建表结构详细参数
  • 网站新闻源码网站开发技术难度
  • 湘潭网站建设多少钱jsp 响应式网站模板
  • PCB设计流程
  • 如何做展示型网站优秀的网站通过什么提供信息
  • 租车公司网站 模板腾讯网站建设专家
  • wordpress 是CMS自己做的网站竞价优化
  • UE5 测量 -2,长度测量:P5绘制定位点之间的连线,P6增加 UI控件,显示距离数据;P7第一个点不显示距离
  • AI操作系统 | LLMs RAG DRAG
  • Python全栈(基础篇)——每日一练详解(day02~day05)
  • SpringBoot中使用Redis(引入案例)