【C++】模板template

news2025/7/20 9:29:17

前言:本教程使用到的工具是vs2010;

目录

为什么要使用模板? 

template模板

        函数模板

        类的模板

template模板的本质 

总结


为什么要使用模板? 

        我们先来大概了解一下模板的概念,下面是菜鸟教程对于模板给出的解释:

        模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。

        模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。

        每个容器都有一个单一的定义,比如 向量,我们可以定义许多不同类型的向量,比如 vector <int> 或 vector <string>

        知道了模板的基本概念之后,我们先来看一段代码:

#include <stdio.h>
#include <Windows.h>

void Sort(int* arr, int nLength)
{
	int ii;
	int kk;
	for(ii=0;ii<nLength-1;ii++)
	{
		for(kk=0;kk<nLength-1;kk++)
		{
			if(arr[kk]>arr[kk+1])
			{
				int temp  = arr[kk];
				arr[kk]   = arr[kk+1];
				arr[kk+1] = temp;
			}
		}
	}
}

int main()
{

    return 0;
}

        这是一段最简单的冒泡排序代码,看不懂没关系,知道怎么用就行;

        继续往下:

        我们定义一个整型数组,里面存放被打乱了的几个整数,如下:

        然后我们调用函数,如下:

 

        调试:

 

        此时顺序是乱的,单步步过F10一下:

 

        已经重新排序;

        好了,我们现在知道这个函数怎么用了,继续往下看:

        我们知道在C语言中'a'和'b'是可以比较的,因为字符类型其实也就是整型,他们的比较是ascii码值的比较,'a'的ascii码值是97,'b'的是98,'c'的99....以此类推,那么我们是不是可以对字符进行排序呢?

        可以;

        我们复制一下上面的整形冒泡排序代码,改一点就行了,如下:

        我们定义一个字符数组,并进行排序,如下:

        调试:

 

        单步F10:

 

        排序成功!

        虽然我们达到了目的,但是我们违背了面向对象编程设计思想: 提高代码的复用性,减少重复代码的编写;

        但是,template模板可以帮我们解决这个问题,这也就是我们为什么要使用模板的原因了;

template模板

        template模板又分为函数模板和类模板,我们先讲函数模板;

        函数模板

        函数模板的格式:

        template<class 形参名,形参名,......>

        返回值类型 函数名(参数列表)

        {

                函数体;

        }

        下面我们给我们的冒泡排序函数加上模板:

 

        !!!!注意看图片上的文字!!!!;

        然后把我们想要自适应类型的地方全部换成T就行了,如下:

        下面我们来测试,先测试int类型,如下:

 

        调试:

 

        F10:

 

        没有问题,接着我们测试char类型:

 

        调试:

 

        F10:

         

        没有问题;

        那么这个函数能对自己定义的类型进行排序吗?

        当然可以;

        如下,我们定义一个类:

        我们首先要知道,如果我们想给我们自己定义的类的对象进行排序的话,那么我们肯定要进行运算符重载;

        我们观察一下刚刚冒泡排序的函数,需要比较类的对象大小的地方有哪些:

        我们可以发现,就这一个地方需要对我们类的对象进行比较大小,而且是大于号;

        那么我们只需要重载'>'即可,如下:

        下面我们进行测试,定义对象,并调用模板函数:

 

        调试:

 

        F10:

 

        ok,没有问题;

        template模板成功的帮我们减少了重复代码的编写,提高了代码的复用性;

        类的模板

        先看代码:

#include <stdio.h>
#include <Windows.h>

template<class T>
class CBase
{
public:
	int  x;
	int  y;
	char a;
	char b;

	int MAX()
	{
		if(x>y) return x;
		if(x<y) return y;
	}

	char MIN()
	{
		if(a>b) return b;
		if(a<b) return a;
	}
};

int main()
{

	return 0;
}

        定义了一个类,类中有四个成员变量;分别是int型的x、y;char型的a、b;

        然后x和y比较谁大返回谁,a和b比较谁小返回谁;

        我们来分析一下,这个类中大概有几个需要自适应类型的地方:

        我们知道了这个类中大概有两个地方需要自适应类型,那么接下来先声明这个类为模板类: 

        因为我们有两个需要自适应的类型,所以这里的class参数有两个;

        下面我们进行模板的替换:

 

         替换好了,下面我们进行测试:

        定义好对象以后,我们给对象的成员进行赋值:

 

        我们调用比较的成员函数:

 

        我们将鼠标悬停到MAX和MIN上:

 

 

        可以看到,在我们CBase<int, char>声明之后,编译器就已经知道MAX和MIN函数的类型了;我们接收一下返回值,如下: 

        观察r和t:

 

        没有问题;

        当然在类中的模板中,也是可以比较类的对象的,依旧需要重载运算符,这里我就不演示了;

template模板的本质 

        下面我们来说一下,template模板的本质:

        代码如下:

#include <stdio.h>
#include <Windows.h>

class CBase
{
public:
	int x;
	int y;
	CBase(int x,int y)
	{
		this->x = x;
		this->y = y;
	}
	bool operator>(CBase& right)		// 因为我们'>'有两个操作数,左是this指针,那么这里的右操作数只能传一个参数;
	{
		return this->x > right.x && this->y > right.y;			// 返回左操作数大于右操作数的结果,如果左大于右就为真,否则为假,达到了大于号的目的;
	}
};

template<class T>				// 只需要在这里加上模板声明即可
void Sort(T* arr, int nLength)
{
	int ii;
	int kk;
	for(ii=0;ii<nLength-1;ii++)
	{
		for(kk=0;kk<nLength-1;kk++)
		{
			if(arr[kk]>arr[kk+1])
			{
				T temp  = arr[kk];
				arr[kk]   = arr[kk+1];
				arr[kk+1] = temp;
			}
		}
	}
}


int main()
{
	int   arr1[5] = {2,1,4,5,3};
    char  arr2[5] = {'c','b','d','a','e'};
    CBase c1(2,2),c2(1,1),c3(4,4),c4(3,3),c5(5,5);
    CBase arr3[5] = {c1,c2,c3,c4,c5};

    Sort(arr1,5);            // 此处下断点

	system("pause");
	return 0;
}

        首先我们先对arr1进行排序,断点下载Sort;编译、调试、alt+8转到反汇编,如下:

        template模板在底层已经识别了改排序是int类型的排序,这没有问题;

        然后我们将arr2也假如排序,那么template底层会怎么做呢?

 

        编译、调试、alt+8反汇编:

 

        可以看到template模板在底层又重新生成了一个函数,用于char类型的排序;

        那么arr3如果加入排序的话,相比大家也都知道结果了,这里我就不测试了;感兴趣的话可以自己测试一下;

        现在我们可以总结一下template的本质是什么了;

        template模板并没有我们想的那么高大上,就是说仅仅一个函数可以千变万化,其实并不是千变万化也并不是一个函数;

        我们刚刚也看到了,模板的底层就是通过看你传入参数的类型,给你分配一个适用你传入类型的函数,你传入int类型,他就给你一个适用int类型的函数,你传入char他就给你一个适用char类型的函数;如果你连续传入int、char等n个类型进行排序,那么他的底层就会给你分配n个函数,并不是一个函数实现的类型自适应;

总结

        1、我们使用模板的目的就是为了提高代码的复用性,减少重复代码的编写;

        2、函数模板的底层并不是只有一个函数完成的,它是根据你传入参数的类型,给你分配一个适用你传入类型的函数;如果你连续传入n个类型,他就会给你分配n个函数;

结语:

        文章讲义到此结束,如果有讲错的地方或者说讲的不好的地方,望指出;感谢大家观看!

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

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

相关文章

每天5分钟快速玩转机器学习算法:带有核函数的支持向量机模型

本文重点 硬间隔和软间隔都是在说样本的完全线性可分或者大部分样本点的线性可分。但我们可能会碰到的一种情况是样本点不是线性可分的,比如: 那么这个时候支持向量机软硬不吃,此时要想解决这个问题,我们可以使用一种魔法,我们将他们映射到一个高维空间中,然后再高维空…

链表相关OJ及方法总结

目录​​​​​​​ 第一类&#xff1a;改变链接关系 第二类&#xff1a;快慢指针 第一类&#xff1a;改变链接关系 1. 删除链表中等于给定值 val 的所有结点。 (1)原地删除 struct ListNode* removeElements(struct ListNode* head, int val){if(headNULL){return head…

一般人我劝你还是要不自学软件测试.....

软件测试基础真的很简单&#xff0c;是个人稍微认真点都能懂&#xff0c;这就是好多人说软件测试简单、易懂、好学&#xff0c;然后就是一顿浮夸的言论&#xff0c;误导那些小白&#xff0c;这里我就给那些轻浮的人泼一桶冷水&#xff0c;懂和学会是一码事吗&#xff1f; 这里…

如何高效填写软件测试缺陷报告?

软件缺陷的描述是软件缺陷报告的基础部分&#xff0c;需要使用简单、准确、专业的术语来描述缺陷。否则&#xff0c;它就会含糊不清&#xff0c;可能会误导开发人员&#xff0c;影响开发人员的效率&#xff0c;也会影响测试人员自身的声誉&#xff0c;准确报告缺陷是非常重要的…

[附源码]java毕业设计基于SSM的酒店管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

高新技术企业的认定条件(三)

十、企业创新能力评价 企业创新能力主要从知识产权、科技成果转化能力、研究开发组织管理水平、企业成长性等四项指标进行评价。各级指标均按整数打分&#xff0c;满分为100分&#xff0c;综合得分达到70分以上&#xff08;不含70分&#xff09;为符合认定要求。具体分值如下&…

opencv4.5.5安装的坑

opencv4.5.5安装的坑 Package opencv was not found in the pkg-config search path. Perhaps you should add the directory containing opencv.pc’ to the PKG_CONFIG_PATH environment variable No package ‘opencv’ found 我把对应目录的opencv4.pc修改成了opencv.pc,运…

记录<一个多SDK中引入ffmpeg出现的top1的crash问题>解决方案

文章目录一. 背景二. 分析、定位crash源代码三. 分析汇编四. 分析源码五. 思考一. 背景 App从某个版本开始突然收到一例高频crash&#xff0c;&#xff0c;crash信息如下 crash栈如下&#xff1a; crash栈信息很少&#xff0c;只能看出是线程刚启动就crash了&#xff0c;内存…

Java【类和对象】,你还没对象?我教你new一个!

文章目录前言一、初识面向对象1.什么是面向对象2.面向对象过程二、类的定义与使用1.什么是类2.如何定义类3.示例三、类的实例化1.什么是类的实例化2.类和对象的说明四、this引用1.为什么要有this引用第一种情况第二种情况2.什么是this引用3.this引用的特征五、对象的构造及初始…

ubuntu上运行make menuconfig两种报错

1&#xff09; 如果如上报错&#xff0c;没有target&#xff0c;这是因为运行这个make的时候没在对应的目录下运行&#xff0c;通常是有make的目录&#xff0c;这种系统性的编译的&#xff0c;则是应该在代码的根目录。在根目录下用根目录下的make。 2&#xff09;然后我来到根…

Restful 接口设计-前言(手把手教你入门到精通)

文章目录前言一&#xff1a;什么是API分类一分类二前言二&#xff1a;Web的发展前言三&#xff1a;传统开发模式VS前后端分离传统的开发模式前后端分离了解API和Web的发展有利于帮助你掌握Restful接口设计 前言一&#xff1a;什么是API API&#xff08;Application Programmi…

第三章 多维随机变量及其分布

思维导图 基础知识 二维随机变量 我们研究一个多维的东西&#xff0c;往往先从较低的维度比如说二维作为主要的研究对象&#xff0c;一个是因为维度低会比较简单&#xff0c;易于理解&#xff1b;另一个则是考试中低维的问题往往更加常见 定义与分布函数 定义上其实很简单&am…

双亲委派机制

Java 虚拟机对 class 文件采用的是按需加载的方式&#xff0c;也就是说当需要使用该类时才会将它的 class 文件加载到内存生成 class 对象。而且加载某个类的 class 文件时&#xff0c;Java 虚拟机采用的是双亲委派模式&#xff0c;即把请求交由父类处理&#xff0c;它是一种任…

【Pytorch with fastai】第 6 章 :其他计算机视觉问题

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

【MySQL】数据库中表的增删查改操作详解

文章目录前言SQL的通用语法一、表的创建与表的新增语法数据类型的介绍演示二、表的删除语法删整张表的语法删记录的语法演示三、表的查询查询整张表&#xff08;一&#xff09;全列查询&#xff08;二&#xff09;指定列查询&#xff08;三&#xff09;带表达式的查询&#xff…

深入ftrace function graph功能

学习完了ftrace的function的基本功能&#xff0c;其作用主要是用来跟踪特定内核函数调用的频次&#xff0c;对于内核&#xff0c;特别是初学者&#xff0c;对于函数的调用关系不清晰&#xff0c;并且内核中有很多函数指针&#xff0c;会把我们弄的摸不着头脑&#xff0c;那么我…

C语言百日刷题第九天

前言 今天是刷题第9天&#xff0c;放弃不难&#xff0c;但坚持一定很酷~ 快来跟我一起刷题吧。 加油&#xff0c;一起努力进步 C语言百日刷题第九天前言76.计算偶数的所有质因子77. 提取不重复的整数78.二进制中1的个数79.猴子分桃80.百钱买百鸡76.计算偶数的所有质因子 输入…

可防离职员工冒用身份,合合信息名片全能王与钉钉用数字名片打造安全“围栏”

名片全能王与钉钉发布数字名片&#xff1a;可防离职员工冒用身份&#xff0c;追踪营销线索 名片是人际交往中的一条纽带。秦汉有竹制的“谒”&#xff0c;唐代纸质的“名刺”也被沿用许久。如今&#xff0c;无实体的数字名片在商务人士中已十分普及&#xff0c;科技加持下&…

共享存储知识

文章目录一、架构图二、RAID&#xff08;廉价冗余磁盘整列&#xff09;三、存储操作四、FusionCompute对接存储五、添加数据存储时的选项六、磁盘配置模式七、磁盘模式八、快照九、FC-SAN一、架构图 SAN&#xff08;存储区域网络&#xff09; IP-SAN&#xff08;SCSI协议封装在…

Linux多线程C++版 线程基础 进程和线程关系 线程分类 Linux线程实现 线程表示

目录1.线程的基础2.进程和线程的关系3.线程分类 了解4.Linux线程实现5.线程标识1.线程的基础 进程是资源管理的最小单位&#xff0c;线程是程序执行最小单位。每个进程有自己的数据段&#xff0c;代码段和堆栈段。线程通常叫做轻型的进程&#xff0c;它包含独立的栈和CPU寄存器…