嵌入式全栈开发学习笔记---C++(函数/类模板)

news2024/12/26 11:08:38

目录

函数模板

模板机制

函数模板语法

函数模板和普通函数的区别

函数模板和普通函数调用规则

函数模板机制

排序模板函数

类模板

类模板语法

模板继承

类模板中的static关键字

模板声明

.hpp文件

类模板小结


上节学习了运算符重载,本节开始学习函数模板和类模板!

函数模板

C++提供了函数模板(function template)。所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。

直接上代码讲解

我们之前说过这个会构成函数重载

两个函数除了返回类型和参数类型不一样,其他几乎一模一样

那我们就可以把这两个函数共同抽象一下,C++里面可以一个通过的函数来表述这两个函数

比如像这样:

但是编译器并不知道这个T是什么,肯定会报错,我们需要声明一下这个T表述的是某种类型的名字

这样我们可以写int或者float型的数据,这个T就会自动替换

这就是函数模板

但是还有一个问题,如果两个参数的类型不一样,那么T就不知道应该是转换成什么

有两种方法可以解决这个问题

首先这两种的调用方式是不同的,第一种方法就是用显示调用,用< >自己指定转换的目标类型

第二种方法:

首先这个是一个虚拟类型的参数列表

这个参数列表可以写多个

并且这两个模板函数构成了重载关系

我们就可以这样调用

但是最后不要写成这种代码,容易造成歧义。

可以这样:

注意T的作用域仅限于一个函数,如果我们再写一个函数,使用这个T,编译器就会报错说这个T没有声明

必须重新声明

还有一个问题,如果模板的参数列表中写着是三个参数,那么显示调用的时候也要写三个参数

模板机制

1、C++提供两种模板机制:函数模板、类模板;

2、类属(比如我们刚刚写的T) — 类型参数化,又称参数模板(可以理解成虚拟参数)。

使得程序(算法)可以从逻辑功能上抽象,把被处理的对象(数据)类型作为参数传递。

总结:

模板把函数或类要处理的数据类型参数化,表现为参数的多态性(比如说只有在运行后才知道指针指向谁),称为类属。

模板用于表达逻辑结构相同,但具体数据元素类型不同的数据对象的通用行为。

为什么需要函数模板机制?

写 n 个函数,交换char类型、int类型、double类型变量的值。

如果使用传统的写法,需要写 n 个函数:

void swap(char c1, char c2);

void swap(int n1, int n2);

void swap(double d1, double d2);

有没有一种机制,可以只写一个函数?当然有,那就是函数模板。

函数模板语法

函数模板定义形式:

template <虚拟类型列表>    

虚拟类型列表的形式为:

typename T1 ,  typename T2 , ... , typename Tn

或     

class T1 ,  class T2 , …… , class Tn  

用typename和class这两个关键字都可以。

函数模板和普通函数的区别

函数模板不允许自动类型转化;

普通函数能够进行自动类型转换;

比如:

template <typename T>

void swap(T x, T y);

swap(1, 'a'); //编译器不会自动转换,要指定

函数模板和普通函数调用规则

1、函数模板可以像普通函数一样被重载;

2、C++编译器优先考虑(调用)普通函数;

3、如果函数模板可以产生一个更好的匹配,那么选择模板;

4、可以通过空模板实参列表的语法限定编译器只通过模板匹配。

比如说现在有一个模板函数和普通函数

如何限定编译器只调用模板函数?

可以这样调用

所以说我们写成show<>(1);这样那调用的就是模板函数,如果我们写成show(1);那肯定就是调用普通函数了。

函数模板机制

1、编译器并不是把函数模板处理成能够处理任意类型的函数;

2、编译器从函数模板通过具体类型产生不同的函数;

3、编译器会对函数模板进行两次编译;

4、在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。

比如:

编译器编译这三句后告诉编译器这个函数是模板函数,也就是说三句只是起到一个通知的作用。

然后走到这里时进行第二次编译,它要回头把T换成int

因此,这就要求模板函数的定义和函数的调用放在同一个文件里面,要不然它就不能回头再次编译了。

排序模板函数

用模板函数来写一个冒泡排序,支持整型,字符串和float等类型排序

直接上代码:

现在换成char类型的数组

小数也可以

现在换成一个学生的类的几个对象的排序,

目前这样是不可以的,

首先在输出的时候array[i]代码一个对象,如果没有输出运算符重载的话,一个对象不能直接被这样输出。

再者,两个对象也不允许这样比较

另外,因为学生的类里面有很多属性,到底是按学生的姓名排序还是按学号/年龄排序?

因此我们要重载输出运算符和>运算符,并且我们需要在>运算符重载中指定一个排序规则。

这样就按学号从大到小排序好了。

类模板

为什么需要类模板?

类模板用于实现类所需数据的类型参数化

类模板在表示如数组、表、图等数据结构显得特别重要,这些数据结构的表示和算法不受所包含的元素类型的影响。

举了例子,链表是用来存放数据的,存放的数据可能是int,char或者其他类型,那么我们就不能在实现链表的时候把类型固定死了。因此链表抽象出来的类就可以用类模板来实现。

类模板语法

类模板由模板说明和类说明构成:

template <虚拟类型列表>

类声明

template <typename T>

class Test

{

        private: T member;//类属参数在类声明中至少出现一次。

};

直接上代码:

像这样类里面有虚拟类型的类我们通常就把它叫做类模板

类模板创建对象的时候必须显示调用

模板继承

继承和类模板-模板类派生普通类(没有虚拟类型)

class TestB : public TestA<int>    //classB为普通类

{

};

继承和类模板-模板类派生模板类

template <Typename T>

class TestB : public TestA<T>    //classB为模板类

{

};

直接上代码讲解:

普通类在继承模板类的时候不可以直接这样写

要这样写,在继承的时候一定要把要继承的那个成员变量的类型确定下来

这样Derived1就把m_a当做char类型继承下来了。

接下来用模板类派生模板类

注:派生的模板类在继承的时候后面的<>里面可以是T可以是其他任何字母,我们为了和基类中的T做个区分,所以就取别的字母。

类模板中的static关键字

1、从类模板实例化的每个模板类有自己的类模板数据成员,该模板类的所有对象共享一个static数据成员;

2、和非模板类的static数据成员一样,模板类的static数据成员也应该在文件范围(全局)定义和初始化;

3、每个模板类有自己的类模板的static数据成员副本。

代码讲解:

我们创建了3个对象,静态变量num的确统计了3个,说明静态变量在模板类的所有成员中的确是共享的。

但是请再看如果我们类型换成char,再创建两个对象,这时num计算出来是多少?

结果是2

因此结论:模板类的所有对象也和非模板类的所有对象一样共享同一个静态成员变量,但是它仅仅是同一种类型的对象共享同一个静态成员变量。

如果我们通过类型去访问写成这样更容易理解

这样写我们可以理解成这两个被示例化成了不同的类。

g++在编译的时候会进行两次编译,它发现第一个是int类型,它会在上面生成一个Array并且虚拟类型是int的类,然后它发现第二个是char类型,它会在上面生成一个Array并且虚拟类型是char的类。所以我们可以把这两个理解成不同的类,既然是不同的类,那第一个类里面有一个静态成员变量,那第二个类里面也有一个自己的静态成员变量。

模板声明

直接上代码:

之前我们写的这三个函数都是在类里面实现的,现在放在外面来实现是这样的:

现在如果我们想要实现这样的操作就必须重载

重载

也可以将全局注释掉

在里面来写

注意:这里虽然是在里面来写,但是它仍然属于全局函数,只是写法不一样。

.hpp文件

类模板里面的最后一个知识点,.hpp是一种文件的格式

这个格式的使用的场景是什么?

刚刚我们写的那个代码虽然是将成员函数都放在类外面来写,但是还不够正规,在正式的工程项目里面我们是分文件来写的,如果将以上代码分成多个文件来写的话就会出问题。

array.h

array.cpp

main.cpp

这样分成三个文件来写的话编译和运行都没有问题

但是当我们把这句加上后再次编译就有问题了,也就是说这样在模板类创建对象的时候有问题

编译和运行是不一样的,编译是从程序的第一行开始,而程序运行是从主函数开始。

问题就出现在模板编译要经历两次编译,第一次是模板定义的地方,比如说构造函数是一个模板就先记下来,等编译到这里的时候,就把这个int代到模板里面的T再去编译,相当于生成了一个这么一个构造函数,里面的T不再是T,而是一个int型。

也就是从头往下编译的时候,先编译模板(告诉编译器这个构造函数是一个模板),之后再根据实际的类型再去编译(把虚拟类型变成实际的类型,相当于实例化),需要两次编译,这就要求模板的定义和模板的调用必须要放在同一个文件里面。

但是我们前面已经把构造函数的定义封装在了另外一个文件了,直接的办法就是将array.cpp里面这些函有定义剪切到main.cpp里面

但是剪过去的话我们的代码就又太乱了,违背了我们多文件编写程序的初衷。

怎么办?

其实我们可以直接在main.cpp里面包含array.cpp

这样编译也能通过

但是我们编译的时候是编译所有的.cpp,那么为了区分,我们又把array.cpp改个名字叫array.hpp(.hpp是介于.cpp和.h之间的一种文件格式)

然后我们把这里也改成.hpp

这样的话我们g++编译的时候就可以直接编译所有的.cpp文件就可以了

这个.hpp文件格式一般是在我们用到模板时才会用到。

类模板小结

1、模板是C++类型参数化的多态工具;C++提供函数模板和类模板。

2、模板定义以模板说明开始。类属参数必须在模板定义中至少出现一次。

3、同一个类属参数可以用于多个模板。

4、类属参数可用于函数的参数类型、返回类型和声明函数中的变量。

5、模板由编译器根据实际数据类型实例化、生成可执行代码;实例化的函数模板称为模板函数;实例化的类模板称为模板类。

6、函数模板可以用多种方式重载。

7、类模板可以在类层次中使用 。

下节开始学习异常和文件!

如有问题可评论区或者私信留言,如果想要进扣扣交流群请私信!

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

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

相关文章

使用 GZCTF 结合 GitHub 仓库搭建独立容器与动态 Flag 的 CTF 靶场+基于 Docker 的 Web 出题与部署+容器权限控制

写在前面 关于 CTF 靶场的搭建&#xff08;使用 CTFd 或者 H1ve&#xff09;以及 AWD 攻防平台的搭建&#xff0c;勇师傅在前面博客已经详细写过&#xff0c;可以参考我的《网站搭建》专栏&#xff0c;前段时间玩那个 BaseCTF&#xff0c;发现它的界面看着挺不错的&#xff0c…

LVGL 控件之复选框(lv_checkbox)和下拉列表(lv_dropdown)

目录 一、复选框1、组成2、设置复选框文本3、复选框部件的状态4、复选框事件5、API 函数 二、下拉列表1、组成2、选项2.1 添加选项2.2 获取当前选中的选项 3、设置3.1 设置列表展开方向3.2 设置下拉列表图标3.3 设置列表常显文本 4、事件5、API 函数 一、复选框 1、组成 复选…

Android studio 导出 release 版本的 .aar 文件

不同的android studio 版本可能会有不同的方案&#xff0c;我针对的是&#xff1a; 首先打开settings: Setting —> Experimental 界面 将选项&#xff1a;【configure all gradle tasks】勾上&#xff1a; 接着点击 File —> Sync Project with Gradle Files 然后&…

【js逆向专题】8.webpack打包

本教程仅供学习交流使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;请各学员自觉遵守相关法律法规。小节目标: 熟悉 webpack打包原理熟悉 webpack打包方式了解 webpack多模块打包 一. webpack打包 概念: webpack 是…

【颤抖不再怕,帕金森患者的活力锻炼秘籍!】

Hey小伙伴们~&#x1f44b; 今天我们来聊聊一个温暖而重要的话题——如何帮助我们的亲人或自己&#xff0c;在帕金森病的挑战下&#xff0c;依然保持生活的活力与光彩&#xff01;&#x1f308; 帕金森病&#xff0c;这个名字听起来或许让人心生畏惧&#xff0c;但它绝不是生活…

地产行业如何利用Java实现精准营销

在当今竞争激烈的地产市场中&#xff0c;如何有效触达潜在客户并促进销售转化&#xff0c;成为众多房企关注的焦点。106短信平台作为一种精准的营销工具&#xff0c;在地产行业中发挥着越来越重要的作用。 支持免费对接试用&#xff1a;乐讯通PaaS平台 找好用的短信平台,选择乐…

AUTO TECH 2025 华南展 第十二届广州国际汽车零部件加工技术及汽车模具展览会——探索未来出行的创新动力

AUTO TECH 2025 华南展 第十二届广州国际汽车零部件加工技术及汽车模具展览会——探索未来出行的创新动力 随着全球汽车工业的不断进步和新能源汽车技术的迅猛发展&#xff0c;2025年11月20-22日在广州保利世贸博览馆将迎来一场行业瞩目的盛会——2025 第十二届广州国际汽车零部…

外接串口板,通过串口打开adb模式

一、依赖库 import subprocess import serial from serial.tools import list_ports import logging import time 二、代码 import subprocessimport serial from serial.tools import list_ports import logging import timedef openAdb(com):# com []# for i in list_por…

无人机之地面站篇

无人机的地面站&#xff0c;又称无人机控制站&#xff0c;是整个无人机系统的重要组成部分&#xff0c;扮演着作战指挥中心的角色。以下是对无人机地面站的详细阐述&#xff1a; 一、定义与功能 无人机地面站是指具有对无人机飞行平台和任务载荷进行监控和操纵能力的一组设备&…

[数据集][目标检测]翻越栏杆行为检测数据集VOC+YOLO格式512张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;512 标注数量(xml文件个数)&#xff1a;512 标注数量(txt文件个数)&#xff1a;512 标注类别…

通过卷积神经网络(CNN)识别和预测手写数字

一&#xff1a;卷积神经网络&#xff08;CNN&#xff09;和手写数字识别MNIST数据集的介绍 卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称CNN&#xff09;是一种深度学习模型&#xff0c;它在图像和视频识别、分类和分割任务中表现出色。CNN通过模仿…

快排的深入学习

目录 交换类排序 一、冒泡排序 1. 算法介绍 2.算法流程 3. 算法性能分析 &#xff08;1&#xff09;时间复杂度分析 &#xff08;2&#xff09; 空间复杂度分析 冒泡排序的特性总结&#xff1a; 二、快速排序 1.算法介绍 2. 执行流程 1). hoare版本 2). 挖坑法 3)…

5.9灰度直方图

目录 实验原理 实验代码 运行结果 实验原理 calcHist 函数通常是指在计算机视觉和图像处理中用于计算图像直方图的一个函数。 cv:calcHist () 用于计算一个或多个数组的直方图。它可以处理图像数据并返回一个表示像素强度分布的向量&#xff08;对于灰度图像&#xff09;或…

Java:集合的相关汇总介绍

主要包含Set(集&#xff09;、 List(列表包含 Queue&#xff09;和 Map(映射)。 1、Collection&#xff1a; Collection 是集合 List、 Set、 Queue 的最基本的接口。 2、Iterator&#xff1a;迭代器&#xff0c;可以通过迭代器遍历集合中的数据。 3、Map&#xff1a;是映射表的…

VTK随笔十三:QT与VTK的交互

一、基于 Ot的 VTK 应用程序 以 VTK 读入一幅 JPG 图像&#xff0c;然后在 Qt 界面上使用 VTK 显示该图像为例&#xff0c;演示QT与VTK的交互。 1、创建QT项目QT_VTK_Demo 2、配置VTK库 在CMakeLists.txt中添加如下代码&#xff1a; 配置完成后重新打开工程加载VTK库。 3、编…

制裁下的转型:俄罗斯加密货币战略布局与人民币挂钩BRICS稳定币的崛起

在国际制裁重压下&#xff0c;俄罗斯正在积极推进加密货币政策改革&#xff0c;通过设立加密货币交易所和推动与人民币挂钩的BRICS稳定币&#xff0c;试图在全球金融体系中谋求新的生存与发展路径。这一系列举措标志着俄罗斯在数字经济领域的重大转向&#xff0c;既是对当前经济…

Linux【5】远程管理

目录 shutdown关机 ifconfig输出网卡信息 ping ip地址——检测连接正常 ssh 【-p port】 userip scp不同主机之间的文件copy 当前文件复制到远程 远程文件复制到本地 复制文件夹 -r shutdown关机 shutdown -r 重启 ifconfig输出网卡信息 ping ip地址——检测连接正常…

集成电路学习:什么是PCB印刷电路板

一、PCB&#xff1a;印刷电路板 PCB&#xff0c;全称为Printed Circuit Board&#xff0c;即印刷电路板&#xff0c;是现代电子设备中不可或缺的基础构件。它作为电子元器件的载体和连接体&#xff0c;在电子设备中发挥着至关重要的作用。以下是对PCB的详细解析&#xff1a; 二…

【C++初阶】一、C++入门(万字总结)

「前言」 「专栏」C详细版专栏 &#x1f308;个人主页&#xff1a; 代码探秘者 &#x1f308;C语言专栏&#xff1a;C语言 &#x1f308;C专栏&#xff1a; C &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 目录 一、关于C 1.1 什么是C 1.2 C 发展史 二、C关键字(C…

5.8幂律变换

目录 示例代码1 运行结果1 示例代码2 运行结果2 补充示例原理 示例&#xff1a;使用cv::pow进行图像处理 代码 运行结果 ​编辑 补充 实验代码3 运行结果3​编辑 在OpenCV中&#xff0c;幂律变换&#xff08;Power Law Transformations&#xff09;是一种常用的图像…