C++初阶:模板初阶

目录

  • 1. 模板的引入
  • 2. 函数模板与类模板
    • 2.1 函数模板
    • 2.2 模板调用方式
    • 2.3 函数模板与普通函数的调用优先性
    • 2.4 类模板
    • 2.5 类模板的构造函数,类模板声明与定义分离

1. 模板的引入

我们来看下面这几个函数:

void swap(int& left, int& right)
{
    int tmp = left;
    left = right;
    right = tmp;
}

void swap(char& left, char& right)
{
    char tmp = left;
    left = right;
    right = tmp;
}

void swap(double& left, double& right)
{
    double tmp = left;
    left = right;
    right = tmp;
}
  1. C++中引入了函数重载,简化了我们对上述功能相同,细节不同函数的调用方式。
  2. 可是,从定义的角度出发,这写有着大量重复性逻辑代码,编写起来无疑是十分繁琐与冗余的。
  3. 上述几个函数,除了参数的类型之外没有任何的区别,因此,我们是否可以进行无关类型只针对逻辑的编程呢,由是,C++提出了泛型编程的概念引入了无关类型的编程方式,模板。

2. 函数模板与类模板

2.1 函数模板

  1. 正如其名,这种方式只是提供了一个模板,其并不是真正的函数,只有在被调用时,其类型才会确定下来,生成对应类型的函数。
  1. 模板参数的定义方式如下:(可定义多个模板参数)
template<typename T1, typename T2,.....>
返回值 函数名(参数列表)
{
	//实现
}
  1. 函数模板生成的函数不是同一份,生成的函数都是被调用时,根据模板参数生成出来的。因此,对模板的使用只是我们将原本自己去做的事情交给了编译器去做,减少了我们的繁复不必要的操作。
template<typename T>
void swap(T& left, T& right)
{
    T tmp = left;
    left = right;
    right = tmp;
}

在这里插入图片描述

4, 多参数类型模板参数的定义

template<typename T1, typename T2>
void Print(T1 num1, T2 num2)
{
	cout << num1 << ' ' << num2 << endl;
}

2.2 模板调用方式

  1. 推演实例化调用:根据所给出的参数类型进行模板参数类型的推演
int num1 = 10;
int num2 = 20;
swap(num1, num2);

char c1 = 'a';
char c2 = 'b';
swap(c1, c2);

double num3 = 11.1;
double num4 = 22.2;
swap(num3, num4);
  1. 显示实例化调用的使用场景:
    <1> 当模板无法根据参数类型推演出应该实例化的类型
    <2> 当函数参数的类型,没有包含模板参数,无法进行推演
template <typename T>
T Add(T left, T right)
{
	return left + right;
}

//无法推导出应该使用哪种类型,进行哪种类型的转换
cout << Add(10, 12.3) << endl;

//没有模板参数类型的函数参数,没有推导的依据
template <typename T>
T* f(int n)
{
	T* data = new T[n];	
}
  1. 显示实例化的调用方式:
//定义方式:
[函数]<类型>(参数列表)

//模板参数类型为int,向int做类型转换
Add<int>(10, 12.3);
//模板参数类型为double,向double做类型转换
Add<double>(10, 12.3);

//返回int类型的指针,指向一段大小为10的动态开辟的空间
int* pa = f<int>(10);

2.3 函数模板与普通函数的调用优先性

  1. 当同时存在类型符合的普通函数,与函数模板时,编译器会去调用哪一个,是否会发生冲突。
    <1> 当存在类型符合存在的普通函数时,优先调用符合的普通函数(可以直接使用,不再生成)
    <2> 当普通函数与调用的参数类型不同,则回调用函数模板
    <3> 当不存在函数模板时,普通函数的类型与函数调用参数的类型不同时,会将参数转换为函数参数类型,然后再对函数进行调用
//场景1:
//优先
int Add(int num1, int num2)
{
	return num1 + num2;
}

template<typename T>
T Add(T num1, T num2)
{
	return num1 + num2;
}

cout << Add(10, 20) << endl;

//场景2:
double Add(double num1, double num2)
{
	return num1 + num2;
}

//优先
template<typename T>
T Add(T num1, T num2)
{
	return num1 + num2;
}

cout << Add(10, 20) << endl;

//场景3:
//类型转换为double后进行调用
double Add(double num1, double num2)
{
	return num1 + num2;
}

cout << Add(10, 20) << endl;

2.4 类模板

  1. 函数之外,C++引入的类(自定义类型),也有着自己需要模板的应用场景
#define STDataType int;

class Stack
{
public:
	Stack(int n = 4)
	{
		data = new STDataType[n];
		top = 0;
		capacity = n;
	}

	~Stack()
	{
		delete[] data;
		capacity = 0;
		top = 0;
	}

private:
	STDataType* data;
	int top;
	int capacity;
};

int main()
{
	//宏的方式可以提高代码复用率
	//存放int类型的数据
	Stack st1;
	//存放double类型的数据
	Stack st2;

	return 0;
}

宏的定义方式虽然可以提高代码的复用率,但以上的场景其无法解决,即同时存在两种存储不同类型的栈。

  1. 类模板的定义方式
//typename ,class关键字皆可,现阶段没有区别
//template <typename T>
template <class T1, class T2,......>
class [类名]
{
	//实现
}

2.5 类模板的构造函数,类模板声明与定义分离

  1. 我们在之前类与对象的学习中,学习过类的默认成员函数,其中构造函数的函数名为类的名称,那么类模板的构造函数的函数名应该是什么呢。
  2. 构造函数的名称为类名,而类模板[类名]<实例化调用类型>为类型名,因此,构造函数名与普通类相同。
  1. 类模板的成员函数声明与定义分离方式:
    <1> 必须在同一文件下,否则报错
    <2> 分离出的定义部分,必须也要加模板参数的声明,声明类域时要使用类型名,具体如下
template<class T>
class [类名]
{
public:
	//函数声明
	[返回值] [函数名]();
}

//定义分离:
template<class T>
[返回值] [类名<T>]::[函数名]()
{
	//实现
}

示例:

//定义在头文件中,头文件被多次展开会重复定义
template<class T>
class Stack
{
public:
    Stack(int n = 4);

    ~Stack()
    {
        delete[] data;
        capacity = 0;
        top = 0;
    }

private:
    T* data;
    int top;
    int capacity;
};

template<class T>
Stack<T>::Stack(int n)
{
    data = new T[n];
    top = 0;
    capacity = n;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/461825.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vuepress-theme-vdoing博客搭建教程

搭建流程 前言 这是笔者搭建个人博客所经历的流程&#xff0c;特附上笔记 笔者个人博客地址&#xff1a;沉梦听雨的编程指南 一、主题介绍 本博客使用的主题为&#xff1a;vuepress-theme-vdoing&#xff0c;相关介绍和使用方法可以参考该主题的官方文档 官方文档快速上手…

java线程池基础

目录 一、线程池基础概念1.1 什么是线程池&#xff1f;1.2 为什么要用线程池&#xff1f;1.3 线程池的工作原理 二、java中的线程池2.1 线程池真正实现类 ThreadPoolExecutor 2.1.2 构造器2.1.3 参数2.1.3.1 workQueue2.1.3.2 threadFactory2.1.3.3 handler 2.2 线程池的使用2.…

超详细解析:在执行一条SQL语句期间发生了什么?

目录 前言MySQL的执行流程Server层连接器查询缓存词法分析器预处理优化器执行器 引擎层具体流程为什么需要redologredolog的组成redolog如何提高性能&#xff1f;redo log与binlog区别 总结 前言 我们学习MySQL时&#xff0c;首先第一个接触到的就是SQL语句了&#xff0c;那么…

MD5算法:密码学中的传奇

title: MD5算法&#xff1a;密码学中的传奇 date: 2024/3/15 20:08:07 updated: 2024/3/15 20:08:07 tags: MD5起源算法原理安全分析优缺点比较技术改进示例代码应用趋势 MD5算法起源&#xff1a; MD5&#xff08;Message Digest Algorithm 5&#xff09;算法是由MIT的计算机…

Linux之shell条件测试

华子目录 用途基本语法格式示例 文件测试参数示例 整数测试作用操作符示例~&#xff1a;检查左侧内容是否匹配右侧的正则表达式 案例分析逻辑操作符符号示例 命令分隔符&>&#xff1a;不管成功与否&#xff0c;都将信息写进黑洞中 用途 为了能够正确处理shell程序运行过…

django开发流式格式后的在nginx的部署的记录

关键记录. django上传代码要导出配置 pip freeze > requirements.txt 这个很关键。后面部署直接读取的 关键记录. django上传代码要导出配置 pip freeze > requirements.txt 这个很关键。后面部署直接读取的 关键记录. django上传代码要导出配置 pip freeze > require…

Python 基础语法:基本数据类型(字典)

为什么这个基本的数据类型被称作字典呢&#xff1f;这个是因为字典这种基本数据类型的一些行为和我们日常的查字典过程非常相似。 通过汉语字典查找汉字&#xff0c;首先需要确定这个汉字的首字母&#xff0c;然后再通过这个首字母找到我们所想要的汉字。这个过程其实就代表了…

Unity的AssetBundle资源运行内存管理的再次深入思考

大家好&#xff0c;我是阿赵。   这篇文章我想写了很久&#xff0c;是关于Unity项目使用AssetBundle加载资源时的内存管理的。这篇文章不会分享代码&#xff0c;只是分享思路&#xff0c;思路不一定正确&#xff0c;欢迎讨论。   对于Unity引擎的资源内存管理&#xff0c;我…

调皮的String及多种玩法(下部)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

0101插入排序-算法基础-算法导论第三版

文章目录 一 插入排序二 循环不变式与插入排序的正确性三 伪代码中的一些约定四 Java代码实现插入排序结语 一 插入排序 输入&#xff1a; n n n个数订单一个序列 ( a 1 , a 2 , ⋯ , a n ) (a_1,a_2,\cdots,a_n) (a1​,a2​,⋯,an​). **输出&#xff1a;**输入序列的一个排…

【how2j练习题】HTML部分综合练习

练习题 1 <html><h1>英雄联盟 &#xff08;电子竞技类游戏&#xff09;</h1> <p> <strong>《英雄联盟》</strong>&#xff08;简称lol&#xff09;是由美国<i>Riot Games</i>开发&#xff0c;中国大陆地区由腾讯游戏运营的网络…

openGauss学习笔记-244 openGauss性能调优-SQL调优-典型SQL调优点-统计信息调优

文章目录 openGauss学习笔记-244 openGauss性能调优-SQL调优-典型SQL调优点-统计信息调优244.1 统计信息调优244.1.1 统计信息调优介绍244.1.2 实例分析&#xff1a;未收集统计信息导致查询性能差 openGauss学习笔记-244 openGauss性能调优-SQL调优-典型SQL调优点-统计信息调优…

4.10.CVAT——3D对象标注

文章目录 1. 创建任务2. 3D 任务工作区3.标准 3D 模式 Standard 3D mode4. 用长方体进行注释4.1. 用shapes进行注释4.2. 使用长方体进行跟踪Tracking 使用 3D 注释工具来标记 3D 对象和场景&#xff0c;例如车辆、建筑物、景观等。 1. 创建任务 要创建 3D 任务&#xff0c;您必…

快速从0-1完成聊天室开发——环信ChatroomUIKit功能详解

聊天室是当下泛娱乐社交应用中最经典的玩法&#xff0c;通过调用环信的 IM SDK 接口&#xff0c;可以快速创建聊天室。如果想根据自己业务需求对聊天室应用的 UI界面、弹幕消息、礼物打赏系统等进行自定义设计&#xff0c;最高效的方式则是使用环信的 ChatroomUIKit 。 文档地址…

面试题手撕篇

参考博客 开始之前&#xff0c;理解递归 手写 浅拷贝 function shallow(target){if(target instanceof Array){return [...resObj]}else{return Object.assign({},target);} }手写深拷贝 const _sampleDeepClone target > {// 补全代码return JSON.parse(JSON.stringify…

mybatis源码阅读系列(一)

源码下载 mybatis 初识mybatis MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解用于配置和原始映射&#xff0c;将接口和 Java 的…

UE4_调试工具_绘制调试球体

学习笔记&#xff0c;仅供参考&#xff01; 效果&#xff1a; 步骤&#xff1a; 睁开眼睛就是该变量在此蓝图的实例上可公开编辑。 勾选效果&#xff1a;

【小白刷leetcode】第15题

【小白刷leetcode】第15题 动手刷leetcode&#xff0c;正在准备蓝桥&#xff0c;但是本人算法能力一直是硬伤。。。所以做得一直很痛苦。但是不熟练的事情像练吉他一样&#xff0c;就需要慢速&#xff0c;多练。 题目描述 看这个题目&#xff0c;说实在看的不是很懂。索性我们直…

GUROBI建模之非线性约束的处理

官方文档 目录 官方文档&#xff1a;GRBModel.AddGenConstrXxx() - Gurobi Optimization 数学规划的约束类型 基本约束(fundamental constraints)&#xff1a; 通用约束(general constraints): 1. GUROBI求解器有针对这类约束的函数&#xff0c;直接调用这类函数即可 2.…

Python-GIS分析之地理数据空间聚类

地理空间数据聚类是空间分析和地理信息系统(GIS)领域的一项关键技术。这种方法对于理解地理数据固有的空间模式和结构、促进城市规划、环境管理、交通和公共卫生等各个领域的决策过程至关重要。本文探讨了地理空间数据聚类的概念、方法、应用、挑战和未来方向。 当模式出现…