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,一经查实,立即删除!

相关文章

linux 利用 ~$() 构造数字

2024.6.1 题目 <?php //flag in 12.php error_reporting(0); if(isset($_GET[x])){$x $_GET[x];if(!preg_match("/[a-z0-9;|#\"%&\x09\x0a><.,?*\-\\[\]]/i", $x)){system("cat ".$x.".php");} }else{highlight_file(__F…

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

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

AI发展的探索与未来展望

随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;技术已经成为当今社会最热门的话题之一。从简单的自动化任务到复杂的决策支持系统&#xff0c;AI技术正以前所未有的速度改变着我们的世界。本文将深入探讨AI技术的发展历程、当前应用、面临的挑战以及未来的…

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;如果有需要…

计算机组成考试测试题

1.下列陈述中正确的是 ( ) 。 A.在DMA周期内&#xff0c;CPU不能执行程序 B.中断发生时&#xff0c;CPU首先执行入栈指令将程序计数器内容保护起来 C.DMA传送方式中,DMA控制器每传送一个数据就窃取一个指令周期 D.输入输出操作的最终目的是要实现 CPU与外设之间的数据传输 res…

负数二进制转成十进制

如果a ’1‘*32&#xff0c;由于a的第0位是’1‘&#xff0c;那么a为负数 转成十进制的负数分成三步&#xff1a; 1.num int&#xff08;a,2) -1 2.num num^0xffffffff ,其中有八个f 3.num -num a 11111111111111111111111111111111 num int(a,2)-1 num num^0xfffffff…

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

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

javascript读取本地目录

在JavaScript中&#xff0c;直接读取本地目录的能力受到浏览器安全限制&#xff0c;因为出于隐私和安全考虑&#xff0c;浏览器的JavaScript环境通常不允许直接访问用户的文件系统。然而&#xff0c;随着Web技术的发展&#xff0c;一些现代浏览器引入了File System API或Web Fi…

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;主键约束&…

Python解方程demo:scipy.optimize -root

该代码利用Python实现解方程功能 使用了scipy.optimize root 求解方程 可以正常调用numpy提供的数学计算函数可以给创建的方程传参 # 导入所需的模块 from scipy.optimize import root import numpy as np# 定义待求解方程 def Equation1(n_eff2, b_1, n_0, n_1, n_2, mode_n…

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;强…

std::string :我是真的不想拼接字符串啊~~~那就“汉阳造”吧

一、场景和炼狱 我想&#xff0c;你肯定也遇到过这样的场景&#xff0c;传入的多个参数要通过字符串拼接成一条指令&#xff0c;各种数据类型&#xff08;我们先只说基本数据类型&#xff09;&#xff0c;然后一通转换&#xff0c;一通拼接。如果处理的多了&#xff0c;这也将…

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

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

Multipass虚拟机磁盘扩容

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