C++编程:模板初阶

 

目录

 一、泛型编程

1、通用版交换函数的实现:

2、模板的引入

二、函数模板

1、函数模板的定义和使用

2、函数模板的实例化

三、类模板

1、类模板的定义和实例化


模板是C++的一项强大特性,犹如中国古代四大发明中的活字印刷术与造纸术融为一体一般,给予C++编程强大的复用能力,允许我们编写与类型无关的通用代码,极大地提高了代码的复用性和可维护性。本文将介绍C++模板编程的基础知识,包括函数模板和类模板。 

 一、泛型编程

泛型编程的核心思想就是编写出一串与类型无关的代码。C++中的模板就提供了这样一种方法,让我们可以定义通用的算法和数据结构。

1、通用版交换函数的实现:

 在学习C语言的时候我们经常会自己命名使用到一种交换函数,swap。

//C语言中交换函数的实现与使用void Swap(int* a, int* b)
{int c = *a;*a = *b;*b = c;
}int main()
{int a = 10, b = 20;Swap(&a, &b);printf("%d %d", a, b);return 0;
}

但是不知道大家是否发现了这一方式的缺陷,没错,就是不能泛用,只能对两个int类型的数据进行交换。倘若我们想要交换两个浮点数类型的数据,又该怎么办呢?

通过前面我们了解了C++不同于C,他支持了函数重载,那我们就多写几个相同内容,相同名字,却只有参数的类型不相同的函数??

传统的函数重载虽然可以实现不同类型的交换:(例如)

void Swap(int* a, int* b)
{int c = *a;*a = *b;*b = c;
}
void Swap(double* a, double* b)
{double c = *a;*a = *b;*b = c;
}
void Swap(char* a, char* b)
{char c = *a;*a = *b;*b = c;
}

可以看见,重载的函数仅仅只是类型不同,代码的复用率极地,只要有新的类型出现,就需要用户自己增加对应的函数。并且代码的可维护性比较低,一个出错可能导致所有的重载出错。

带着这个问题,于是C++中引入了模板,想让编译器根据不同的类型自己生成一个对应的函数。

2、模板的引入

那么什么又是模板呢?

我们想到,打造铁器时通常都是将铁水倒进一个提前准备好的模具里,这样冷却下来的形状就会是模具的形状。

如果在C++中,也能够存在一个这样的模具,通过给这个模具填充不同的材料(数据类型),来获得不同的形状材料(也就是具体类型的代码),那就会节省很多时间与空间,根据这个思想,模板就出现了!


二、函数模板

1、函数模板的定义和使用

函数模板是一种用于定义一组相关函数的蓝图。这些函数模板在使用时会根据实参类型生成具体的函数版本。

以swap为例,我们要写的模板就是:

template <typename T>
void Swap(T& a, T& b)
{T c = a;a = b;b = c;
}

(typename是用来定义模板参数的关键字,也能用class代替)

在编译时,编译器会根据传入的实参类型生成具体类型的函数。例如:

int a = 5, b = 10;
Swap(a, b);  // 编译器生成处理int类型的Swap函数double x = 5.5, y = 10.5;
Swap(x, y);  // 编译器生成处理double类型的Swap函数

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

2、函数模板的实例化

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

隐式实例化:编译器根据实参推演模板参数的实际类型。

template<typename T>
T Add(const T& left, const T& right) 
{return left + right;
}int main() 
{int a = 10, b = 20;double x = 10.5, y = 20.5;Add(a, b);  // 实例化为int类型的Add函数Add(x, y);  // 实例化为double类型的Add函数return 0;
}

但如果交换的x与b呢?

这样编译就不会通过,因为在编译期间,当编译器看见该实例化时,需要推演其实参类型,通过实参将T推演为int或者double,但此时模板参数列表只有一个T,编译器无法确定将T转换为int还是double而报错。在模板中,编译器一般不会进行类型转换操作,因为一旦转换出现问题,编译器就得背黑锅,只有普通函数允许自动类型转换。

此时有两种处理方式,第一种时用户强制转换类型,二就是使用显示实例化。

显式实例化:在函数名后的尖括号中指定模板参数的实际类型。

int a = 10;
double b = 20.5;
Add<int>(a, b);  // 显式实例化为int类型的Add函数
//如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

 对于非模板函数和同名函数模板,如果其他条件相同,在调动时会优先调用非模板参数而不会从该模板中产生一个实例。如果模板可以产生一个具有更好匹配的函数,那么才会调用模板进行实例化。

三、类模板

类模板是用于定义一组相关类的蓝图,实例化时根据模板参数生成具体类。

1、类模板的定义和实例化

以一个简单的顺序表为例,

template<typename T>
class Vector 
{
public:Vector(size_t capacity = 10): _pData(new T[capacity]), _size(0), _capacity(capacity){}~Vector() {delete[] _pData;}void PushBack(const T& data) {if (_size < _capacity) {_pData[_size++] = data;}}void PopBack() {if (_size > 0) {--_size;}}size_t Size() const {return _size; }T& operator[](size_t pos) {assert(pos < _size);return _pData[pos];}private:T* _pData;size_t _size;size_t _capacity;
};

实例化类模板:

int main() 
{Vector<int> vecInt;vecInt.PushBack(10);vecInt.PushBack(20);Vector<double> vecDouble;vecDouble.PushBack(10.5);vecDouble.PushBack(20.5);return 0;
}
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后面跟<>,然后将实例化类型放在<>中,类模板的名字不是真正的类,实例化的类才是真正的类。(Vector<int>才是类型)
我们C++中的stl库中的vector,list等容器之所以可以存储不同类型的数据,主要就是运用了类模板。
通过本文的介绍,我们了解了C++模板编程的基本概念和使用方法。模板为我们提供了一种编写高效、可复用代码的手段,极大地提高了代码的通用性和可维护性。通过掌握模板编程的技巧,我们可以编写出更加强大和灵活的C++程序。
希望对大家有所帮助,谢谢观看。

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

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

相关文章

牛客网刷题 | BC103 金字塔图案

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 KiKi学习了循环&am…

C++:细谈Sleep和_sleep

ZINCFFO的提醒 还记得上上上上上上上上上上上上上上上上上上&#xff08;上的个数是真实的&#xff09;篇文章吗&#xff1f; 随机应变——Sleep()和_sleep() 但在ZINCFFO的C怪谈-02中&#xff1a; 我不喜欢Sleep...... 奤&#xff1f;媜煞鷥&#xff01; 整活&#xff01;…

Java的JDK环境变量配置(Windows)

只写了需要配置的环境变量 注&#xff1a;从JDK1.5开始&#xff0c;配置Java环境变量时&#xff0c;不再需要配置CLASSPATH&#xff0c;只需要配置JAVA_HOME和Path 1、配置JAVA_HOME 找到自己的JDK位置&#xff0c;我这里是 C:\dev\java\jdk-17.0.119在环境变量-系统变量中&…

电商商城管理系统

前言&#x1f440;~ 将近一个月没更新了&#xff0c;最近忙着学校的大作业&#xff0c;一个是微信小程序的、一个是互联网编程的&#xff0c;也是忙完了这个大作业&#xff0c;这个大作业前端使用了vue、后端使用了java&#xff0c;接下来展示一些效果图&#xff0c;如果有需要…

深度学习复盘与论文复现A

文章目录 一、查漏补缺复盘1、python中zip()用法2、Tensor和tensor的区别3、计算图中的迭代取数4、nn.Modlue及nn.Linear 源码理解5、知识杂项思考列表6、KL散度初步理解 二、处理多维特征的输入1、逻辑回归模型流程2、Mini-Batch (N samples) 三、加载数据集1、Python 魔法方法…

TPL0401B使用教程

1.前言 前面做程控放大器的时候&#xff0c;有除开AD602&#xff0c;还有一个AD620&#xff0c;性能更好&#xff0c;不过是通过外部电阻来控制放大倍数的&#xff0c;不过要是接滑动变阻器就太不优雅了&#xff0c;而且单片机怎么控制滑动变阻器&#xff1f;&#xff08;难不…

C++双层Vector容器详解

双层Vector容器 关于C中二维vector使用 双层vector的运用细节 插入元素 //正确的插入方式 vector<vector<int> > A; //A.push_back里必须是vector vector<int> B; B.push_back(0); B.push_back(1); B.push_back(2); A.push_back(B); B.clear(); B.push_back…

MySQL:CRUD进阶(七千五百字)

文章目录 前置文章&#xff1a;&#x1f4d1;1. 数据库约束&#x1f324;️1.1 约束类型&#x1f324;️1.2 NULL约束&#x1f324;️1.3 Unique&#xff1a;唯一约束&#x1f324;️1.4 Default&#xff1a;默认值约束&#x1f324;️1.5 Primary key&#xff1a;主键约束&…

RK3588搭建QT开发环境

目录 1 我的RK3588开发板 2安装opencv 3 安装QT 4 摄像头节点 1 我的RK3588开发板 我把它放客厅了&#xff0c;连接电视。然后我在书房远程登录做开发&#xff0c; 2安装opencv 这里不下载源码编译了&#xff0c;直接用apt-get安装opencv sudo apt-get update sudo apt-g…

使用eclipse自动生成实体类

前言 在软件开发过程中&#xff0c;经常需要创建大量的实体类来映射数据库表或者表示业务模型。手动编写实体类既费时又容易出错&#xff0c;因此许多集成开发环境&#xff08;IDE&#xff09;提供了自动生成实体类的功能。本篇博客将介绍如何在 Eclipse 中内置功能来快速生成实…

最新的CleanMyMac X4.15.4中文破解版新功能介绍及CleanMyMac 安装激活指南

知名的Mac系统清理软件CleanMyMac发布了最新的CleanMyMac X4.15.4&#xff0c;更换了矩形图标&#xff0c;更好的融合和兼容macOS Snoma系统。新版CleanMyMac 支持Intel芯片和苹果M1/M2芯片的Mac。 优化 Mac 电脑&#xff0c;用 CleanMyMac X4.15.4中文版 就够了&#xff01;强…

三丰云评测:免费虚拟主机和免费云服务器体验

今天我来为大家分享一下我的三丰云评测体验。三丰云是一家提供免费虚拟主机和免费云服务器的服务商&#xff0c;为了方便大家了解他们的服务&#xff0c;我特地注册了他们的免费虚拟主机和免费云服务器进行试用。在实际体验中&#xff0c;我发现三丰云的服务表现非常出色。首先…

Multipass虚拟机磁盘扩容

Multipass 是一个用于轻松创建和管理 Ubuntu 虚拟机的工具&#xff0c;特别适合开发环境。要使用 Multipass 扩大虚拟机的磁盘容量&#xff0c;你需要经历几个步骤&#xff0c;因为 Multipass 自身并不直接提供图形界面来调整磁盘大小。不过&#xff0c;你可以通过结合 Multipa…

HTTP的系统登录页面,如何避免明文传输用户密码?

对于系统登录页面来说&#xff0c;我们作为开发人员&#xff0c;应该没有陌生的吧。就像下面这样子。 点击登录&#xff0c;调用/login 接口。来看下面截图中的 载荷(payload)数据&#xff0c;其中&#xff0c;密码 password 的值是明文。 如果你的站点使用的是HTTPS协议&…

Adobe InDesign 专业桌面排版软件下载安装,Id软件丰富的排版和设计工具!

Adobe InDesign这款革命性的应用程序不仅彻底改变了出版业的生产流程&#xff0c;更引领着设计领域向前迈进。 在Adobe InDesign的众多强大功能中&#xff0c;对OpenType字体的支持堪称其一大亮点。OpenType字体不仅拥有更加丰富的字体样式和字符集&#xff0c;还具备更为灵活…

Qt Designer工具如何修改MainWindow窗口的标题

Qt Designer工具如何修改MainWindow窗口的标题 在MainWindow的属性编辑器中选择“windowTitle”后面一栏修改成期望的窗口标题名称即可。 按住“ctrlR”即可查看可视化界面的窗口标题

单片机超声波测距+WTD588D语音播报的设计

第一章 绪论 1.1 课题设计目的及意义 1.1.1设计的目的 随着科学技术的快速发展&#xff0c;超声波在测距中的应用越来越广。但就目前的急速水平来说&#xff0c;人们可以具体利用的测距技术还十分有限&#xff0c;因此&#xff0c;这是一个正在蓬勃发展而又有无限前景的技术…

【通信专题】I2C通信硬件概述

通信协议在组织设备之间通信时扮演着重要角色。它基于系统要求而以不同方式进行设计。此类协议具有明确的、为实现成功通信而协商一致的规则。 I2C历史 I2C,即Inter-Integrated Circuit,是一种常用的串行通信协议。I2C总线创建于1982年,由飞利浦公司设计,旨在利用简单、稳…

【Python打包成exe】

Python打包成exe 前言一、理论知识打底二、实操开始----pyinstaller【Base环境下】【这是一个失败案例】规规矩矩 总结 前言 先放点参考 这个字多&#xff0c;写得很详细⇨用 Pyinstaller 模块将 Python 程序打包成 exe 文件&#xff08;全网最全面最详细&#xff0c;万字详述…

Neural Filters:风景混合器

Ps菜单&#xff1a;滤镜/Neural Filters/创意/风景混合器 Neural Filters/CREATIVE/Landscape Mixer 风景混合器 Landscape Mixer滤镜通过与另一个图像混合或改变诸如时间和季节等属性&#xff0c;神奇地改变景观。 “风景混合器”滤镜利用人工智能和机器学习技术&#xff0c;首…