C++模板初阶小笔记

news2024/11/13 15:57:42

目录

一.泛型编程

二.函数模板

1.函数模板语法梳理:

2.函数模板的实例化: 

3.函数模板的显式实例化: 

4.函数模板使用时的注意事项

三.类模板

1.类模板的语法梳理

2.类模板中声明和定义分离的成员函数


一.泛型编程

泛型编程:编写不依赖于具体数据类型的通用代码,是代码复用的一种手段。

二.函数模板

1.函数模板语法梳理:

C++中可以编写形参类型待定函数模板

假如我们现在要设计一个各种类型变量都通用的变量交换函数:

template <typename T1>
void swap(T1& Element1, T1& Element2)
{
	T1 tem = Element1;
	Element1 = Element2;
	Element2 = tem;
}

函数模板书写格式:
template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(形参列表){函数体}

  • template是定义模板关键字
  • typename是定义模板待定变量类型关键字
  • T1,T2...代表待定类型名,用于作为函数模板的形参类型名
  • 注意函数模板本身并不是一个可调用的函数,由函数模板生成可调函数的过程是由编译器在编译阶段完成的

2.函数模板的实例化: 

上面代码段中的swap就是一个函数模板函数模板代表了一个函数家族,swap的形参Element1和Element2的类型都是待定的,实际调用swap函数时:

  • 编译器会根据函数调用语句传入函数的实参的类型生成对应的重载函数(编译器生成模板的重载函数的过程叫做函数模板的实例化),并调用重载函数。
  • 也就是说,函数模板转变为可调函数的过程是在代码编译的阶段由编译器根据具体函数调用语句中实参的类型类完成的
  • 比如:
    template <typename T1>                    定义函数模板
    void swap(T1& Element1, T1& Element2)
    {
    	T1 tem = Element1;
    	Element1 = Element2;
    	Element2 = tem;
    }
    
    
    
    class Date
    {
    public:
    	Date(char year = 0)
    		:_year(year)
    	{
    		cout << "constructor" << endl;
    	}
    private:
    	char _year;
    };
    
    int main()
    {
    	int a = 1;
    	int b = 2;
    	swap(a, b);                   交换一对整形变量
    
    	double d = 1.0;
    	double c = 2.0;
    	swap(d, c);                   交换一对浮点型变量
    
    	Date date1('b');
    	Date date2('c');
    	swap(date1, date2);           交换一对Date对象
    
    	return 0;
    }

代码编译阶段编译器将函数模板转化为可调函数的过程图解:

  • 这种函数模板的实例化方式称为隐式实例化(让编译器自己根据实参推演模板参数的实际类型),函数模板还可以显式实例化。
  • 函数重载机制是支持函数模板化编程的底层机制

3.函数模板的显式实例化 

函数调用语句的函数名后的<>中指定模板参数的实际类型。

template <typename T1>                    定义函数模板
void swap(T1& Element1, T1& Element2)
{
	T1 tem = Element1;
	Element1 = Element2;
	Element2 = tem;
}


int main ()
{
    double d = 1.0;
	double c = 2.0;
	swap<double>(d, c);    
    return 0;
}

 

4.函数模板使用时的注意事项

  • 一个非模板函数可以和一个同名的函数模板同时存在。
    // 专门处理int的加法函数
    int Add(int left, int right)
    {
        return left + right;
    }
    // 通用加法函数
    template<class T>
    T Add(T left, T right)
    {
        return left + right;
    }
    void Test()
    {
        Add(1, 2);      //与非模板函数匹配,编译器不需要特化
        Add<int>(1, 2); //调用编译器特化的Add版本(显式实例化模板)
    }

  • 对于非模板函数同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。但是如果模板可以产生一个具有更好匹配的函数, 编译器将选择模板实例化函数。
     

    // 专门处理int的加法函数
    int Add(int left, int right)
    {
        return left + right;
    }
    // 通用加法函数
    template<class T1, class T2>
    T1 Add(T1 left, T2 right)
    {
        return left + right;
    }
    void Test()
    {
        Add(1, 2);     // 与非函数模板类型完全匹配,不需要函数模板实例化
        Add(1, 2.0);   // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
    }

  • 模板实例化函数不能自动对实参进行强制类型转换,但普通函数可以自动对实参进行强制类型转换 

三.类模板

1.类模板的语法梳理

类模板的定义格式:

template<typename T1, typename T2, ..., typename Tn> //类模板的未定变量类型列表
class Date     //类模板名
{
     T1 _mem1; //类中未定类型的成员的声明
     T2 _nem2;
     ....      
}; 
  • T1,T2...具体的类型名在创建类对象时由用户自行指定

比如现在定义一个栈类的模板:

class Date
{
public:
	Date(char year = 0)
		:_year(year)
	{
		cout << "constructor" << endl;
	}
private:
	char _year;
};


template <typename T>                        //Stack类模板
class Stack
{
public:
	Stack(int capacity = 4, int nums = 0)    //类的构造函数
		:_data = nullptr					 //构造函数初始化列表
		, _capacity = capacity
		, _nums = nums
	{
		_data = new T[_capacity];		     //为栈申请初始的堆区空间
	}

	~Stack()                                 //类的析构函数
	{
		delete[] _data;					     //将栈申请的堆区空间还给系统
		_data = nullptr;
	}
private:
	T* _data;
	int _capacity;
	int _nums;
};

int main()
{
	Stack<int> a;           //创建一个存储int类型数据的栈对象
	
	Stack<double>b;			//创建一个存储double类型数据的栈对象

	Stack<Date>c;           //创建一个存储Date对象的栈对象

	return 0;
}

注意:

 

用类模板的方式定义的栈对象使用起来十分方便,可以用于存储各种类型的数据(一般来说实现一个栈类需要上百行代码,实现三种数据类型的栈就要三份代码,然而如果使用模板型编程方式,代码书写量就可以大大减少 

2.类模板中声明和定义分离的成员函数

如果类模板中的成员函数放在类外进行定义时,需要加上模板参数列表,比如:

template <typename T>
class Stack
{
public:
	Stack(int capacity = 4, int nums = 0)    //类的构造函数
		:_data = nullptr					 //构造函数初始化列表
		, _capacity = capacity
		, _nums = nums
	{
		_data = new T[_capacity];		     //为栈申请初始的堆区空间
	}

	~Stack();     //类的析构函数的声明, 将析构函数的定义放在类模板外面
private:
	T* _data;
	int _capacity;
	int _nums;
};

template <typename T>
Stack<T>::~Stack()     //类的析构函数的定义
{
	delete[] _data;
	_data = nullptr;
}

模板型编程模式可以让代码变得更简洁,简洁的代码维护起来才更加的方便高效。 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】类和对象---什么是类?

目录1.面向过程和面向对象初步认识2.类的引入2.1使用struct定义类3.类的定义3.1类的两种定义方式&#xff1a;3.2成员变量命名规则的建议3.3成员函数与成员变量定义的位置建议4.类的访问限定符及封装4.1访问限定符4.2封装5.类的作用域6.类的实例化7.类对象模型7.1如何计算类对象…

Kali Linux渗透

Kali Linux是基于Debian的Linux发行版&#xff0c; 设计用于数字取证操作系统。每一季度更新一次。 黑盒测试&#xff0c;它是通过测试来检测每个功能是否都能正常使用。在测试中&#xff0c;把程序看作一个不能打开的黑盒子&#xff0c;在完全不考虑程序内部结构和内部特性的情…

从C语言的使用转换到C++(上篇)——刷题、竞赛篇

文章目录 一、C的基础语法详解 1、1 输入、输出流 1、2 C中头文件的使用 1、3 C中变量的声明 1、4 C中的string类 1、5 C中的引用& 二、C中常见函数使用详解 2、1 排序sort函数详解 2、2 cctype头文件中的函数 三、总结 标题&#xff1a;从C语言的使用转换到C&#xff08;上…

④【Spring】IOC - 基于注解方式 管理bean

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 注解管理Bean一、注解的功能二、四个典型注解三…

day24|491.递增子序列、46.全排列、47.全排列 II

491.递增子序列 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情况…

源码深度解析Spring Bean的创建,手把手的一步一步带你看源码

在源码深度解析Spring Bean的加载 中对Bean的加载源码进行了梳理,在本文将对bean的创建进行梳理 在doGetBean()方法中createBean()方法准备创建bean,调用源码如下: createBean() 方法的源码如下: 从代码中可以得出,createBean() 方法涉及4个步骤: 步骤一: 根据设置的class属…

[论文笔记]A ConvNet for the 2020s

目录 Abstract Modernizing a ConvNet: a Roadmap 2.1.Training Techniques 2.2. Macro Design 2.3. ResNeXt-ify 2.4. Inverted Bottleneck 2.5. Large Kernel Sizes 2.6. Micro Design 论文&#xff1a;https://arxiv.org/abs/2201.03545 代码&#xff1a;GitHub - f…

扩散模型(Diffusion model)代码详细解读

扩散模型代码详细解读 代码地址&#xff1a;denoising-diffusion-pytorch/denoising_diffusion_pytorch.py at main lucidrains/denoising-diffusion-pytorch (github.com) 前向过程和后向过程的代码都在GaussianDiffusion​这个类中。​ 常见问题解决 Why self-condition…

盒相关样式-----diaplay:block、inline

盒的基本类型 CSS中的盒分为block类型与inline类型&#xff0c;例如&#xff0c; div元素与p元素属于block类型&#xff0c; span元素与a元素属于inline类型。 block类型的盒对应的是html中的块级元素&#xff0c;inline类型的盒对应了html中的行内元素。 行内元素与块级元素…

JavaScript 练手小技巧:键盘事件

键盘事件应该是鼠标事件之外&#xff0c;使用频率最高的 JS 事件了吧&#xff1f; 一般用于全局或者表单。 键盘事件由用户击打键盘触发&#xff0c;主要有keydown、keypress、keyup三个事件。 keydown&#xff1a;按下键盘时触发。Ctrl、Shift、Alt 等和其它按键组合时&…

BCNF与3NF

今天学了一下午这个BCNFBCNFBCNF与3NF3NF3NF&#xff0c;有感而发&#xff0c;特来总结。好像好久不打键盘了&#xff0c;这手好像刚长出来的一样。本文浅显的分析一下两种范式的关系与不同以及判断方法和分解算法&#xff0c;以做总结。 BCNFBCNFBCNF范式的定义如下: 设属性集…

linux 常用指令大全

目录一、基本指令指令基本格式1、ls1.1 ls相关选项2、pwd3、cd4、mkdir4.1、mkdir相关选项5、touch6、cp6.1 cp相关选项7、mv8、rm8.1、rm相关选项9、输出重定向10、cat11、df11.1、df 相关选项12、free12.1、free 相关选项13、head13.1、head相关选项14、tail14.1 tail相关选项…

day13 二叉树 | 144、二叉树的前序遍历 145、二叉树的后序遍历 54、二叉树的中序遍历

二叉树基础 二叉搜索树 二叉搜索树是一个有序树。 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b;若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b;它的左、右子树也分别为二叉排序树 下面这两棵…

零食商城|基于springboot的零食商城

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

GuLi商城-简介-项目介绍、分布式基础概念、微服务架构图

一、项目简介 1 、项目背景 1 &#xff09;、电商模式 市面上有 5 种常见的电商模式 B2B、B2C、C2B、C2C、O2O&#xff1b; 1 、 B2B 模式 B2B (Business to Business)&#xff0c; 是指商家与商家建立的商业关系。 如&#xff1a;阿里巴巴 2 、 B2C 模式 B2C (Business…

Win7安装高版本的NodeJS方法,亲测可用

Win7安装高版本的NodeJS方法 正常情况下&#xff0c;Win7所能支持的Node.js最高版本为:V13.14&#xff0c;在开发过程中&#xff0c;git下来的项目由于node版本比较高的原因&#xff0c;好多package都不能还原或出现诸多警告 网络大神分享的安装高版本的方法&#xff1a; 1、…

Express 通过 CORS 或 JSONP 解决跨域问题

文章目录参考描述同源策略同源同源策略示例CSRF 攻击解决跨域问题CORSCORS 响应头部Access-Control-Allow-Origin简单请求预检请求预检请求包含的两次请求解决CORS 中间件使用 CORS 中间件处理跨域请求JSONP通过原生 JS 向服务器端发起 JSONP 请求通过 jQuery 向客户端发起 JSO…

mysql:如何在windows环境下配置并随意切换两种mysql版本

系列文章目录 文章目录系列文章目录前言一、去官网下载zip安装包二、配置创建my.ini文件2.环境变量3、使用管理员身份打开dos命令窗口4、安装mysql8的服务和初始化data5、启动6 错误解决&#xff1a;修改mysql8服务的注册表最后前言 之前安装过5.7的版本 后来由于需要 就安装了…

天龙八部TLBB从0到1搭建教程-上

服务器的配置选择与购买 我们需要准备的东西,是环境安装和4核8G的服务器一台。 其实购买服务器的地方很多以下这些服务商都可以,具体看服务器的配置选择,像这种4核8G的 服务器价格在260-400之间一台仅供参考,当然还有带防的服务器价格就偏高了阿里云、腾讯、百度、西部数码…

年后公司新来一00后卷王,我们这帮老油条真干不过.....

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。这不&#xff0c;我们公司来了个00后&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 2023年春…