初始C++模板

1.泛型编程

1.1什么事泛型编程

在学习C语言时,我们时常会有这样的烦恼:

在针对每一种不同的类型变量进行函数传参或者是运算处理时,我们总是编写不同的函数或者是进行不同的处理,才能达到目的,这时,我们就会想到,有没有什么操作能够让我们只写一种函数就能堆所有的百年来那个类型都进行处理,在C++中,就实现了泛型编程。

我们先来看看下面的代码:

这是C语言的交换函数:

void swapi(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
void swapd(double* x, double* y)
{double tmp = *x;*x = *y;*y = tmp;
}
int main()
{int i = 12;int j = 20;printf("整形, 交换前:i:%d, j:%d\n", i, j);swapi(&i, &j);printf("整形, 交换后:i:%d, j:%d\n", i, j);double in = 12.5;double jn = 32.6;printf("双精度浮点型, 交换前:i:%lf, j:%lf\n", in, jn);swapd(&in, &jn);printf("双精度浮点型, 交换后:i:%lf, j:%lf\n", in, jn);return 0;
}

 从上面的代码我们可以看出,在C语言中我们进行,相同的操作,但由于受限于变量的类类型,我们还是需要进行许多操作,这不由得让我们觉得过于冗余。

但是反泛型编程就能够很好的解决这样的问题:

我们来及看下面的代码:


using namespace std;template<class T>
void Swap(T& x, T& y)
{T tmp = x;x = y;y = tmp;
}
int main()
{int i = 12;int j = 20;printf("整形, 交换前:i:%d, j:%d\n", i, j);Swap(i, j);printf("整形, 交换后:i:%d, j:%d\n", i, j);double in = 12.5;double jn = 32.6;printf("双精度浮点型, 交换前:i:%lf, j:%lf\n", in, jn);Swap(in, jn);printf("双精度浮点型, 交换后:i:%lf, j:%lf\n", in, jn);return 0;
}

通过反省编程,我们就轻松的实现了,各类型的数据交换,避免了C语言中的一些无法避免的问题,是程序更加的见解,可读性也变得更高!

接下来,我们就来正式的了解一下什么是泛型编程。

2. 泛型模板

我们可以想象一下,在一个制作工艺中,我们通常可以通过相同的模板来实现将不同的类型的材料,塑造吃呢公同样的形状,在这里,我们就需要用到一种模具来实现这样的操作。

如果C++中,也存在这样的模板的话,通过在模板上填充不同的材料(类型变量),来获取不同才来哦的构建(即生成相应的代码),那将会节省许多的头发。巧的就是,前人早已将树种好,我们现在只需要再次乘凉就好。

所以综上:泛型编程就是:编写与类型无关代码,是代码复用的手段。模板是反省编程的基础。

3.函数模板

3.1函数模板的概念 

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

3.2函数模板的模式 

template<typename T1, typename T2,......,typename Tn>

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

template<typename T>
void Swap( T& left, T& right)
{
T temp = left;
left = right;
right = temp;
}

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

3.3函数模板实现的原理

函数 模板是一个蓝图,他本省并不是函数,是编译器使用方式产生具体类型的函工具。所以其实魔板就是将我们本应该重复做的事情交给了编译器来做,这样可以可以提高效率。

在编译器的编译阶段,对于函数模板,编译器需要根据传入的参数来推演出生成对应函数的类型,将T确定为double类型,然后产生一份专门处理double类型的代码 ,对于其他的类型也都是这样的。

3.4函数模板的实例化

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

隐式实例化和显示实例化

1.隐式实例化:让编译器根据实参来推断模板参数1的实际类型

template<class T>
T Add(const T& left, const T& right)
{
return left + right;
} i
nt main()
{
int a1 = 10, a2 = 20;
double d1 = 10.0, d2 = 20.0;
Add(a1, a2);
Add(d1, d2);
/*
该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要
通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板
一个T,
编译器无法确定此处到底该将T确定为int 或者 double类型而报错
注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要
背黑锅
Add(a1, d1);
*/
// 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
Add(a, (int)d);
return 0;
}

 2.显示实例化:在函数的使用时,在函数名的后面<>中指定模板参数的实际类型

i
nt main(void)
{
int a = 10;
double b = 20.0;
// 显式实例化
Add<int>(a, b);
return 0;
}

如果类型不匹配,编译器会尝试进行隐式类型转化,如果无法进行正确的转化,编译器就会报错。

3.5模板参数的匹配原则

1.一个非模板函数可以和一个同名的函数一起存在,而且这个函数在进行调用时。会有先调用已经存在的类型的函数,同时,模板函数还是可以经过实例化生成这个函数。

// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
} /
/ 通用加法函数
template<class T>
T Add(T left, T right)
{
return left + right;
} v
oid Test()
{
Add(1, 2); // 与非模板函数匹配,编译器不需要特化
Add<int>(1, 2); // 调用编译器特化的Add版本
}

2.对于非模板函数和对应同名的函数模板, 如果其他条件相同,在调用时会有优先调用非模板函数而不会从该模板中产生一个实例。如果模板可以产生一个更好的实力函数,那么,编译器还是会考虑从模板重中生成。

// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
return left + right;
}void Test()
{
Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的
Add函数
}

3.模板函数不允许自动类型转换,但是普通函数可以进行这样的操作!

4.类模板

4.1类模板的定义方式 

template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
#include<iostream>
using namespace std;
// 类模版
template<typename T>
class Stack
{ p
ublic:
Stack(size_t capacity = 4)
{
_array = new T[capacity];
_capacity = capacity;
_size = 0;
}void Push(const T& data);
private:
T* _array;
size_t _capacity;
size_t _size;
};
// 模版不建议声明和定义分离到两个文件.h 和.cpp会出现链接错误,具体原因后面会讲
template<class T>
void Stack<T>::Push(const T& data)
{
// 扩容
_array[_size] = data;
++_size;
} 
int main()
{
Stack<int> st1; // int
Stack<double> st2; // double
return 0;
}

 4.2类模板的实例化

类模板的实例化与函数的模板实例化有所不同,类模板实例化需要在类模板名字后面跟<>,然后就爱那个实力化的类型放在<>中即可,类模板的名字不是真正的类,而是实例化后的结果才是真正的类!!!


/ Stack是类名,Stack<int>才是类型
Stack<int> st1; // int
Stack<double> st2; // double

好,今天的内容就到这里,咱们下期再见,拜拜!! 

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

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

相关文章

(undone) 阅读 MapReduce 论文笔记

参考&#xff1a;https://pdos.csail.mit.edu/6.824/papers/mapreduce.pdf 摘要&#xff1a;简单介绍了 MapReduce 是在大型分布式系统上工作的 Introduction 的内容总结&#xff1a; 1.介绍背景&#xff1a;为什么我们需要分布式系统&#xff1f;MapReduce 的意义是哪些 2.简…

2024.9.26C++作业

1. 什么是虚函数&#xff0c;什么是纯虚函数&#xff1f; 1.虚函数在基类中声明&#xff0c;使用virtual关键字修饰成员函数&#xff0c;并且允许在派生类中重写。 2.在运行时&#xff0c;允许基类指针或者引用调用这个函数时&#xff0c;根据实际对象类型调用派生类&#xff…

大数据新视界 --大数据大厂之数据清洗工具 OpenRefine 实战:清理与转换数据

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

尚硅谷vue3+TypeScript笔记大全

源码及视频&#xff1a;通过百度网盘分享的文件&#xff1a;尚硅谷vue3 链接&#xff1a;https://pan.baidu.com/s/19zVM5Xsr1UP7tZ4D0mhVqA?pwdgmta 提取码&#xff1a;gmta 1. Vue3简介 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piec…

Qualcomm AI Hub模型优化1: Whisper-Base-En导出及问题解决

1 从Qualcomm AI Hub Module中选择Whisper-Base-En模块部署 1.1 进入module虚拟环境 python3 -m venv qai_hub_models_env && source qai_hub_models_env/bin/activate1.2 使用pip安装高通音频转录包 pip install "qai_hub_models[whisper_base_en]" 1.3…

人工智能对话系统/AI助理/PC/公众号/h5/小程序

>>>系统简述&#xff1a; GPTCMS基于TP6UniappVUE3开发&#xff0c;已集成文心一言、灵犀星火、ChatGLM&#xff08;清华旗下&#xff09;、讯飞星火&#xff08;即将&#xff09;、api2d、意间AI、ChatGPT、GPT3.5、GPT4、Stable Diffusion、MidJourney-V4、MidJour…

基于Python大数据可视化的民族服饰数据分析系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

第十届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)

一.题目分析 &#xff08;1&#xff09;.题目 &#xff08;2&#xff09;.题目分析 1.参考配置界面 注意上限和下限的调整&#xff0c;上限值必须大于下限值&#xff0c;低于下限LD2会闪烁&#xff0c;低于上限LD1会闪烁 2.按键功能分析 B1&#xff1a;显示界面和设置界面相互切…

Java IO 和 NIO

在 Java 编程中&#xff0c;输入输出&#xff08;IO&#xff09;是不可或缺的部分&#xff0c;随着技术的发展&#xff0c;Java 的 IO 系统也经历了显著的变化。本文将深入探讨 Java IO 和 NIO 的历史、优缺点以及适用场景。 1. Java IO 的历史 Java IO 包&#xff08;java.i…

Solidity智能合约中的异常处理(error、require 和 assert)

Solidity 中的三种抛出异常方法&#xff1a;error、require 和 assert 在 Solidity 开发中&#xff0c;异常处理是确保智能合约安全性和正确性的关键步骤。Solidity 提供了三种主要方法来抛出异常&#xff1a;error、require 和 assert。本文将详细介绍这三种方法的用途、实现方…

nginx+keepalived健康检查案例详解(解决nginx出现故障却不能快速切换到备份服务器的问题)

文章目录 简介配置过程前置环境请看创建健康检查脚本结果测试 简介 在我们通过nginxkeepalived实现高可用后&#xff0c;会发现nginx出现故障的时候keepalived并不会将虚拟ip切换到备份服务器上其原理就是nginx和keepalived是两个独立的服务&#xff0c;Nginx的故障状态不会触…

使用Docker-Compose部署SpringBoot项目的案例

Docker-Compose是Docker官方的一个开源项目&#xff0c;主要用于实现对Docker容器集群的快速编排和管理。该项目由Python编写&#xff0c;通过调用Docker服务提供的API来管理容器。只要所操作的平台支持Docker API&#xff0c;就可以利用Docker-Compose进行编排管理。Docker-Co…

【微服务即时通讯系统】——brpc远程过程调用、百度开源的RPC框架、brpc的介绍、brpc的安装、brpc使用和功能测试

文章目录 brpc1. brpc的介绍1.1 rpc的介绍1.2 rpc的原理1.3 grpc和brpc 2. brpc的安装3. brpc使用3.1 brpc接口介绍 4. brpc使用测试4.1 brpc同步和异步调用 brpc 1. brpc的介绍 1.1 rpc的介绍 RPC&#xff08;Remote Procedure Call&#xff09;远程过程调用&#xff0c;是一…

X86下一文带你构建Apollo9.0运行环境(基于Ubuntu20.04避坑版)

X86下一文带你构建Apollo9.0运行环境基于Ubuntu20.04避坑版 前言准备安装基础软件1.安装Docker19.03安装Nvidia驱动安装配置Nvidia container toolkit 下载Apollo源码&#xff08;笔者下载的是releases下9.0.0版本&#xff0c;大家可以参考&#xff09;编译Apollo9.0下载资源包…

如何使用GitHub Desktop管理GitLab库

不管是新手还是老手&#xff0c;Github Desktop都是在苹果系统和Windows系统上管理与创建项目的不错的方式&#xff0c;GitHub Desktop都能够让在GitHub上的工作流更为简单快捷。 注意&#xff0c;以下步骤只支持原版的GitHub Desktop 第一步 从这下载GitHub Desktop打开你的G…

【hot100-java】【柱状图中最大的矩形】

R9-栈篇 面积最大矩形的高度一定是 heights 中的元素 简单解释&#xff0c;就是说&#xff0c;最大高度必然是heights中的一个元素&#xff0c;我们假设是h&#xff0c;然后我们基于h&#xff0c;左右拓展&#xff0c;尽量拓展到h越来越高&#xff08;符合单调栈&#xff09;&a…

手机改IP地址怎么弄?全面解析与操作指南

在当今数字化时代&#xff0c;IP地址作为设备在网络中的唯一标识&#xff0c;其重要性不言而喻。有时候&#xff0c;出于隐私保护、网络访问需求或其他特定原因&#xff0c;我们可能需要更改手机的IP地址。然而&#xff0c;对于大多数普通用户来说&#xff0c;如何操作可能还是…

Redis 篇-深入了解 Redis 中的 RESP 通信协议与内存回收(过期 key 处理、内存淘汰策略)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Redis 通信协议 - RESP 协议 2.0 Redis 内存回收 2.1 Redis 内存回收 - 过期 key 处理 2.1.1 Redis 是如何知道一个 Key 是否过期呢&#xff1f; 2.1.2 是不是 TT…

Linux基础(三):安装CentOS7(系统安装+桥接联网+换源)

1.分区设置 由于使用 GPT 的关系&#xff0c; 因此根本无须考虑主/延伸/逻辑分区的差异。CentOS 默认使用 LVM 的方式来管理你的文件系统。使用GPT进行分区&#xff1a; 开机管理程序&#xff08; boot loader&#xff09; 使用CentOS 7.x默认的grub2软件。 2.各种分区格式 …

DataLight(V1.4.5) 版本更新,新增 Ranger、Solr

DataLight&#xff08;V1.4.5&#xff09; 版本更新&#xff0c;新增 Ranger、Solr DataLight 迎来了重大的版本更新&#xff0c;现已发布 V1.4.5 版本。本次更新对平台进行了较多的功能拓展和优化&#xff0c;新增了对 Ranger 和 Solr 服务组件的支持&#xff0c;同时对多项已…