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

【C++】模板的一点简单介绍

模板

    • 前言
    • 泛型编程
    • 函数模板
      • 概念
      • 格式
      • 函数模板的原理
      • 函数模板的实例化
    • 类模板
      • 类模板的定义格式
      • 类模板的实例化

在这里插入图片描述

前言

这篇博客讲的是模板的一些基本知识,并没有那么深入,但是如果你是为了过期末考试而搜的这篇博客,我觉得下面讲的是够了的。

之后会再出一篇深入讲解模板的博客。

泛型编程

先说一个例子:

如何实现一个通用的交换函数呢?

学了C++之后,我们有了函数重载这个东西。这是C不具有的语法。
我们可以通过函数重载来实现相同函数名交换不同类型的变量。像下面这样:

void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}
void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}

当然用C也可以,但是C实现的话,只能搞成不同函数名来实现不同变量的交换,而且还没有引用的语法。

但是不论是上面的函数重载还是用C来实现,都好麻烦,当我们每次想要交换新类型的交换的时候都要再重写一个函数。

也就是下面的缺点:

  1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
  2. 代码的可维护性比较低,一个出错可能所有的重载均出错

活字印刷,相信大家都听过。

在这里插入图片描述

通过改变模具中的字来印刷出不同的文章。

那能否告诉编译器一个模具,让编译器根据不同的类型利用该模具来生成代码呢?

如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同文字块(类型),来获得不同文字的文章(即生成具体类型的代码)。

这就是本篇博客要讲的模板。

目录中的泛型编程是指编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

模板分为两类,函数模板和类模板。
在这里插入图片描述

函数模板

概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

格式

//写函数前要加这个
template<typename T1, typename T2,......,typename Tn>
//typename后面的T1,这种就相当于我们定义变量时候的变量名,是
//随便取的,只不过这里是类型名。常用的还有K,V,跟T合起来就是KTV。//然后再写函数
返回值类型 函数名(参数列表){}

来个交换的例子:
在这里插入图片描述
下面都是OK的。
在这里插入图片描述

typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)。

在这里插入图片描述
目前阶段,记住写成typename和class都是可以的。

再来个交换int和交换double的例子:
在这里插入图片描述
但是记住,上面的代码中,交换int和交换double走的不是一个函数。

函数模板的原理

大家都知道,瓦特改良蒸汽机,人类开始了工业革命,解放了生产力。机器生
产淘汰掉了很多手工产品。本质是什么,重复的工作交给了机器去完成。

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

在这里插入图片描述
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

如何证明呢?
看图(稍微懂一点反汇编就行):
在这里插入图片描述
右侧的反汇编中,交换int和交换double的函数地址是不一样的。

其实也可以对应到活字印刷术当中,我们想要有一份文章的拷贝,不是用活字印刷里面的木头块来读的,而是通过那些木头块来把文章印到纸上来读的。

所以上面的就很好理解了,不是用模板,而是用模板来实例化出对应的函数来使用。

其实,C++标准库中也是有交换的函数的,只不过用起来是小写swap。
在这里插入图片描述
可以看到,标准库中实现的就是用的模板。
我们可以直接使用:
在这里插入图片描述

函数模板的实例化

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

  1. 隐式实例化:让编译器根据实参推演模板参数的实际类型
    先给个能跑的例子:编译器自动推演在这里插入图片描述
    再给个跑不了的例子:
    在这里插入图片描述
    出现上面问题的原因是a和d1的类型是不相同的,而模板函数中两个参数的类型是相同的,但是我们偏要生成一个int和double的函数,这样是生成不了的。因为编译器不能决定到底是用int还是用double来实现。编译器就犯难了,只能报错,不然就得背黑锅。

  2. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

但是我们之前写的函数是可以进行隐式类型转换的。比如说下面这样:
在这里插入图片描述
如果想用模板来实现两个不同类型相加的时候,可用以下方法:
在这里插入图片描述
但是这样非常挫。

可以用下面的显示实例化来实现。

  1. 显示实例化:在函数名后的<>中指定模板参数的实际类型
    在这里插入图片描述
    这个方法在函数模板中不是那么常用,但是在类模板中就非常常用了。
    再给个在函数模板中适用的场景。
    在这里插入图片描述

上面不能直接使用func,因为模板中的T是不确定的。
这时候就要用到<>了。
在这里插入图片描述

当我们同时拥有模板和一个功能相同的加法函数的时候会发生什么?
在这里插入图片描述
会像上面这样,但是上面的写法是很挫的,不建议同时出现功能相同的函数模板。

类模板

类模板的定义格式

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

和函数模板很像。

类模板的是使用场景是什么呢?
我们来写一个简单的类模板。

在这里插入图片描述

如果想将类模板中的的成员函数在类外定义的话,得像这样:
在这里插入图片描述

还要说一点就是模板不支持分离编译。 声明放在.h 定义放在.cpp。
至于为什么的话放到后面深入讲模板的博客中说。

类模板的实例化

在这里插入图片描述
如果不指明T的类型,是会报错的。
那么用类模板的时候就要显示指出T的类型。
在这里插入图片描述

最后再给一个顺序表的例子:

直接把代码给出来:

template<typename T>
class Stack
{
public:Stack(size_t capacity = 4):_data(nullptr),_top(0),_capacity(0){if (capacity > 0){_data = new T[capacity];_top = 0;_capacity = 4;}}~Stack(){delete[] _data;_data = nullptr;_top = _capacity = 0;}void Push(const T& a){if (_capacity == _top){int newcapacity = _capacity == 0 ? 4 : 2 * _capacity;T* newdata = new T[newcapacity];if (_data){memcpy(newdata, _data, sizeof(T) * _capacity);delete[] _data;}_data = newdata;_capacity = newcapacity;}_data[_top] = a;++_top;}void Pop(){assert(_top);--_top;}bool Empty(){return _top == 0;}const T& Top(){return _data[_top - 1];}private:T* _data;size_t _top;size_t _capacity;
};int main()
{Stack<int> s;s.Push(1);s.Push(2);s.Push(3);s.Push(4);s.Push(5);while (!s.Empty()){cout << s.Top() << " ";s.Pop();}cout << endl;return 0;
}

其中最重要的是下面main函数中的Stack<int> s; 这条语句。

到此结束。。。

相关文章:

【C++】模板的一点简单介绍

模板 前言泛型编程函数模板概念格式函数模板的原理函数模板的实例化 类模板类模板的定义格式类模板的实例化 前言 这篇博客讲的是模板的一些基本知识&#xff0c;并没有那么深入&#xff0c;但是如果你是为了过期末考试而搜的这篇博客&#xff0c;我觉得下面讲的是够了的。 之…...

SpringCloud概述

前言 什么是微服务&#xff1f; ​ 微服务是一种面向服务的架构(SOA)风格&#xff0c;其中&#xff0c;应用程序被构建为多个不同的小型服务的集合而不是单个应用程序。与单个程序不同的是&#xff0c;微服务让你可以同时运行多个独立的应用程序&#xff0c;而这些独立的应用…...

Metal入门学习:GPU并行计算大数组相加

一、编程指南PDF下载链接(中英文档&#xff09; 1、Metal编程指南PDF链接 https://github.com/dennie-lee/ios_tech_record/raw/main/Metal学习PDF/Metal 编程指南.pdf 2、Metal着色语言(Metal Shader Language:简称MSL)编程指南PDF链接 https://github.com/dennie-lee/ios_te…...

关于在spyder,jupyter notebook下创建虚拟环境(pytorch,tensorflow)均有效

anaconda下载地址 https://www.anaconda.com/download/ 下载完成后打开anaconda目录下的 anaconda prompt 在命令行中输入下面的命令创建一个叫tf2.0的虚拟环境&#xff08;“tf2.0”是建立的Conda虚拟环境的名字&#xff0c;可以自拟&#xff09; conda create -n tf2.0 p…...

oracle 闪回恢复

oracle 闪回恢复 闪回恢复区主要通过3个初始化参数来设置和管理&#xff1a; db_recovery_file_dest&#xff1a;指定闪回恢复区的位置 db_recovery_file_dest_size&#xff1a;指定闪回恢复区的可用空间大小 db_flashback_retention_target&#xff1a;指定数据库可以回退的时…...

LeetCode 322 零钱兑换

题目&#xff1a; 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。你可以认为每种硬币的数量…...

面试篇SpringMVC是什么以及工作原理

1&#xff0c;什么是SpringMVC呢&#xff1f; 它是Spring的一种设计模式&#xff0c;一款框架。 2&#xff0c;MVC分别代表什么&#xff1f; M代表模型即model的缩写&#xff0c;指业务逻辑层模型。V代表视图即View的缩写&#xff0c;指视图层。C则是controller的缩写&#xff…...

jQuery-层级选择器

<!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>层级选择器</title> <style type"text/css"> …...

【Java数据结构】——第十节(下).选择排序与堆排序

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Java初阶数据结构 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目…...

45道SQL题目陆续更新

文章目录 学习视频配置环境第一天内连接 外连接第二天第三天 学习视频 学习视频 配置环境 四张表 配置四张表的sql语句 #创建发据库 create database frogdata charsetutf8&#xff1b;use frogdata;# 学生表 Student create table Student( SId varchar(10), Sname var…...

在线PS软件有哪些不错的推荐

许多新的UI设计合作伙伴非常关心在线ps工具的选择。现在市场上有各种各样的ps网页替代工具&#xff0c;数量众多&#xff0c;令人眼花缭乱。本文简要介绍了10个在线PS工具&#xff0c;我相信一定有一个适合你&#xff01; 1.即时设计 即时设计是一款在线 UI 设计工具&#xf…...

Java实现天气预报功能

如果要实现类似百度天气、手机App这样的天气预报功能该如何实现&#xff1f;首先想到的是百度... 背景&#xff1a; 最近公司做了一个项目&#xff0c;天气预报的功能也做上去了&#xff0c;不仅有实时天气、未来7天预报的功能、还有气象预警的功能。 天气包括基本天气、白天夜…...

python循环语句

while循环 Python中&#xff0c;while循环只要在条件&#xff08;表达式&#xff09;为真的情况下&#xff0c;就会一直重复执行相应的循环代码块。 while语句的语法格式如下&#xff1a; while 条件表达式&#xff1a;代码块while语句执行的具体流程为&#xff1a;首先判断…...

多线程基础(一)线程基础信息、synchronized 锁概念

1. 基本概念&#xff1a; 程序&#xff1a; 程序是一些保存在磁盘上的指令的有序集合&#xff0c;是静态的。程序包括&#xff1a;内存资源、IO资源、信号处理等。&#xff08;如&#xff1a;XX.exe&#xff09; 进程&#xff1a; 进程是程序执行的过程&#xff0c;包括了动态…...

JAVA期末考内容知识点的梳理

作者的话 前言&#xff1a;这些都是很基本的&#xff0c;还有很多没有写出来&#xff0c;重点在于考试复习&#xff0c;包括后四章的内容 前面内容请参考JAVA阶段考内容知识点的梳理 一、集合、流 课堂总结1集合 集合概念&#xff1a; 保存和盛装数据的容器&#xff0c;将许多…...

为什么要使用Thrift与Protocol Buffers?

编码数据的格式 程序通常&#xff08;至少&#xff09;使用两种形式的数据&#xff1a; 在内存中&#xff0c;数据保存在对象、结构体、列表、数组、散列表、树等中。 这些数据结构针对 CPU 的高效访问和操作进行了优化&#xff08;通常使用指针&#xff09;。如果要将数据写…...

oa是什么意思?oa系统哪个好用?

一、oa是什么意思 oa&#xff08;Office Automation办公自动化&#xff09;是一种将智能化科技应用于企业管理中的应用系统。它可以通过电脑网络、互联网等技术手段&#xff0c;将企业的各种业务流程、各种业务数据进行集成和处理&#xff0c;将各种业务流程和各种业务数据统一…...

Linq和C# Lambda表达式

什么是Linq 简介 Linq (Language Integrated Query) 是一种语言集成的查询技术&#xff0c;可以在C#和其他.NET语言中使用。Linq允许我们使用一种类SQL的语言来查询数据&#xff0c;这使得代码更加简洁和易于阅读。Linq提供了一种通用的查询接口&#xff0c;可以用于查询各种…...

蓝桥:前端开发笔面必刷题——Day2 数组(三)

文章目录 &#x1f4cb;前言&#x1f3af;两数之和 II&#x1f4da;题目内容✅解答 &#x1f3af;移除元素&#x1f4da;题目内容✅解答 &#x1f3af;有序数组的平方&#x1f4da;题目内容✅解答 &#x1f3af;三数之和&#x1f4da;题目内容✅解答 &#x1f4dd;最后 &#x…...

人工智能专栏第四讲——人工智能的未来展望与机遇

目录 一、人工智能的未来展望 二、人工智能在各领域的应用 三、人工智能的机遇 四、总结...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...