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

【c++】 模板初阶

泛型编程

写一个交换函数,在学习模板之前,为了匹配不同的参数类型,我们可以利用函数重载来实现。

void Swap(int& a, int& b)
{int c = a;a = b;b = c;
}
void Swap(char& a, char& b)
{char c = a;a = b;b = c;
}
void Swap(double& a, double& b)
{double c = a;a = b;b = c;
}//...

虽然这样似乎解决了问题,但是这样的设计写着太过麻烦,只要出现新类型就需要写新的函数,代码的复用率很低。有没有什么可以让我们一劳永逸呢?模板就可以实现这一功能。

这种通过抽象和模板化来编写可重用和灵活的代码以此提升代码的可读性和维护性,同时避免代码重复的方式称为泛型编程。

函数模板

函数模板是c++中的一类机制,通过在函数定义中使用模板参数,我们可以编写一个函数,而在调用时根据实际参数的类型自动生成相应的版本。

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

这样编译器就可以根据传入的参数类型来生成对应的Swap()函数,大大提高了代码的复用率。下面我们来尝试运行一下。

template <class T>
void Swap(T& a, T& b)
{T c = a;a = b;b = c;
}int main()
{int a,b;a = 1; b = 2;double c, d;c = 0.0; d = 1.2;Swap(a, b);Swap(c, d);cout << a << "  " << b << endl;cout << c << "  " << d << endl;return 0;
}

我们发现,调用Swap()之后,int类型的ab和double类型的cd都完成了交换。但是他们是否调的是同一个函数呢?

转到反汇编: 

我们发现两次调用的是不同的Swap()函数,根据传入参数类型的不同 ,编译器会生成不同的函数。然后再调用生成的函数。

函数模板的实例化

通过函数模板生成对应函数的过程叫做函数实例化。

当模板的参数只有一个时,却传入了不同类型的变量,编译器无法推导出T的类型,出现了推导错误。

template <class T>
void Swap(T& a, T& b)
{T c = a;a = b;b = c;
}int main()
{int a, b;a = 1; b = 2;double c, d;c = 0.0; d = 1.2;Swap(a, c);Swap(b, d);cout << a << "  " << b << endl;cout << c << "  " << d << endl;return 0;
}

 然后我们就会发现报错了:

我们写的模板中是两个相同的类型T,在实例化的过程中出现了推导问题不能生成对应的函数。

不重新定义模板参数的情况下,要解决这个问题有两种方法:

1.推导实例化,任然让编译器来推导出T的类型,通过强制类型转换来让传入的变量类型一致。

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
using namespace std;template <class T>
T Add(const T& a, const T& b)
{return a + b;
}int main()
{int a1 = 10, a2 = 5;double d1 = 11.2, d2 = 12.6;cout << Add(a1, (int)d1) << endl;cout << Add((double)a1, d1) << endl;return 0;
}

2.显示实例化,不用编译器推导T的类型,直接指定T的类型。

template <class T>
T Add(const T& a, const T& b)
{return a + b;
}int main()
{int a1 = 10, a2 = 5;double d1 = 11.2, d2 = 12.6;/*cout << Add(a1, (int)d1) << endl;cout << Add((double)a1, d1) << endl;*/cout << Add<int>(a1, d1) << endl;cout << Add<double>(a1, d1) << endl;return 0;
}

这两种方法都可以解决推导问题,但是都对精度有影响。 并且当T不作参数时,只能使用显示实例化。

模板函数的匹配原则

当函数模板和现成的函数同时存在时,编译器会选择现成的函数。很简单,有现成的为什么还要自己生成呢。

T Add(const T& a, const T& b)
{return a + b;
}
int Add(int a,int b)
{return (a + b) * 10;
}int main()
{int a = 1;int b = 2;cout << Add(a, b) << endl;return 0;
}

类模板 

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
using namespace std;template <typename T>
class Stack
{
public:Stack(int n = 4):_array(new T[n]), _capacity(n), _size(0){}void push(const T& x){if (_capacity == _size){T* tmp= new T[2 * _capacity];memcpy(tmp, _array, _size * sizeof(T));delete[] _array;_array = tmp;_capacity *= 2;}_array[_size++] = x;}~Stack(){delete[] _array;_array = nullptr;_capacity = _size = 0;}
private:T * _array;int _capacity;int _size;
};int main()
{//类模板都是显示实例化Stack<int> str1;str1.push(1);str1.push(2);str1.push(3);return 0;
}

底层: 

 

首先,类模板不能推导实例化。

 编译器不能自动推导出类中T的类型,这点和T作返回值不作参数的情况一样,编译器没有推理其中T类型的依据,所以不手动规定类的类型,就会报错。先比于c语言,用类模板的类可以储存不同类型的数据而不用重新在写一个Stack。

当定义和声明分离时,需要重新声明模板,并且99%的情况下,不能把定义和声明放到两个文件中。 

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
using namespace std;template <typename T>
class Stack
{
public:Stack(int n = 4):_array(new T[n]), _capacity(n), _size(0){}void push(const T& x);~Stack(){delete[] _array;_array = nullptr;_capacity = _size = 0;}
private:T * _array;int _capacity;int _size;
};
template <typename T>//重新声明模板void Stack<T>::push(const T& x)
{if (_capacity == _size){T* tmp = new T[2 * _capacity];memcpy(tmp, _array, _size * sizeof(T));delete[] _array;_array = tmp;_capacity *= 2;}_array[_size++] = x;
}
int main()
{//类模板都是显示实例化Stack<int> str1;str1.push(1);str1.push(2);str1.push(3);return 0;
}

 

相关文章:

【c++】 模板初阶

泛型编程 写一个交换函数&#xff0c;在学习模板之前&#xff0c;为了匹配不同的参数类型&#xff0c;我们可以利用函数重载来实现。 void Swap(int& a, int& b) {int c a;a b;b c; } void Swap(char& a, char& b) {char c a;a b;b c; } void Swap(dou…...

R 语言 data.table 大规模数据处理利器

前言 最近从一个 python 下的 anndata 中提取一个特殊处理过的单细胞矩阵&#xff0c;想读入R用来画图&#xff08;个人比较喜欢用R可视化 &#xff09;&#xff0c;保存之后&#xff0c;大概几个G的CSV文件&#xff0c;如果常规方法读入R&#xff0c;花费的时间比较久&#x…...

Java 静态代理详解:为什么代理类和被代理类要实现同一个接口?

在 Java 开发中&#xff0c;代理模式是一种常用的设计模式&#xff0c;其中代理类的作用是控制对其他对象的访问。代理模式分为静态代理和动态代理&#xff0c;在静态代理中&#xff0c;代理类和被代理类都需要实现同一个接口。这一机制为实现透明的代理行为提供了基础&#xf…...

OpenCV C++霍夫圆查找

OpenCV 中的霍夫圆检测基于 霍夫变换 (Hough Transform)&#xff0c;它是一种从边缘图像中识别几何形状的算法。霍夫圆检测是专门用于检测图像中的圆形形状的。它通过将图像中的每个像素映射到可能的圆参数空间&#xff0c;来确定哪些像素符合圆形状。 1. 霍夫变换的原理 霍夫…...

H.264编解码介绍

一、简介 H.264,又称为AVC(Advanced Video Coding),是一种广泛使用的视频压缩标准。它由国际电信联盟(ITU)和国际标准化组织(ISO)联合开发,并于2003年发布。 H.264的发展历史可以追溯到上个世纪90年代。当时,视频压缩技术的主要标准是MPEG-2,但它在压缩率和视频质…...

Java | Leetcode Java题解之第450题删除二叉搜索树中的节点

题目&#xff1a; 题解&#xff1a; class Solution {public TreeNode deleteNode(TreeNode root, int key) {TreeNode cur root, curParent null;while (cur ! null && cur.val ! key) {curParent cur;if (cur.val > key) {cur cur.left;} else {cur cur.rig…...

【CViT】Deepfake Video Detection Using Convolutional Vision Transformer

文章目录 Deepfake Video Detection Using Convolutional Vision Transformerkey points**卷积视觉变压器**FLViT实验总结Deepfake Video Detection Using Convolutional Vision Transformer 会议/期刊:2021 作者: key points 提出了一种用于检测深度伪造的卷积视觉变压器…...

安卓主板_MTK4G/5G音视频记录仪整机及方案定制

音视频记录仪方案&#xff0c;采用联发科MT6877平台八核2* A78 6* A55主频高达2.4GHz, 具有高能低耗特性&#xff0c;搭载Android 12.0智能操作系统&#xff0c;可选4GB32GB/6GB128GB内存&#xff0c;运行流畅。主板集成NFC、双摄像头、防抖以及多种无线数据连接&#xff0c;支…...

Qt 教程全集目录公布(方便查阅)

点击上方"蓝字"关注我们 Qt 安装 以下是常见安装方法和软件获取 Qt4Qt5Qt6版本下载(在线和离线)【网址】...

云计算SLA响应时间的matlab模拟与仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 用matlab模拟&#xff0c;一个排队理论。输入一堆包&#xff0c;经过buffer&#xff08;一个或者几个都行&#xff09;传给server&#xff0c;这些包会在buffer里…...

ARTS Week 42

Algorithm 本周的算法题为 2283. 判断一个数的数字计数是否等于数位的值 给你一个下标从 0 开始长度为 n 的字符串 num &#xff0c;它只包含数字。 如果对于 每个 0 < i < n 的下标 i &#xff0c;都满足数位 i 在 num 中出现了 num[i]次&#xff0c;那么请你返回 true …...

10.2学习

1.IOC控制反转 IoC&#xff08;Inverse of Control:控制反转&#xff09;是⼀种设计思想&#xff0c;就是将原本在程序中⼿动创建对象的控制权&#xff0c;交由Spring框架来管理。 IoC 在其他语⾔中也有应⽤&#xff0c;并⾮ Spring 特有。 ​ IoC 容器是 Spring⽤来实现 IoC …...

【数一线性代数】021入门

Index 推荐阅读&#xff1a;https://blog.csdn.net/weixin_60702024/article/details/141729949分析实现总结 推荐阅读&#xff1a;https://blog.csdn.net/weixin_60702024/article/details/141729949 给定二叉树的根节点root&#xff0c;计算其叶节点的个数。 分析实现 类似…...

(k8s)kubernetes中ConfigMap和Secret

转载&#xff1a;ConfigMap 一、ConfigMap介绍 ConfigMap是一种API对象&#xff0c;用来将非机密性的数据保存到键值对中。使用时&#xff0c;Pod可以将其用作环境变量、命令行参数或存储卷中的配置文件。 ConfigMap将你的环境配置信息和容器镜像解耦&#xff0c;便于应用配置…...

stm32四足机器人(标准库)

项目技术要求 PWM波形的学习 参考文章stm32 TIM输出比较(PWM驱动LED呼吸灯&&PWM驱动舵机&&PWM驱动直流电机)_ttl pwm 驱动激光头区别-CSDN博客 舵机的学习 参考文章 stm32 TIM输出比较(PWM驱动LED呼吸灯&&PWM驱动舵机&&PWM驱动直流电机)…...

基于Hive和Hadoop的共享单车分析系统

本项目是一个基于大数据技术的共享单车分析系统&#xff0c;旨在为用户提供全面的单车使用信息和深入的出行行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 S…...

基于SSM和vue的机票订购管理系统

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM和vue的机票订购管理系统2拥有两种角色 管理员&#xff1a;用户管理、机票管理、订票管理、公告管理、广告管理、系统管理、添加机票等 用户&#xff1a;登录注册、订票、查看公…...

【rCore OS 开源操作系统】Rust 练习题题解: Enums

【rCore OS 开源操作系统】Rust 练习题题解: Enums 摘要 rCore OS 开源操作系统训练营学习中的代码练习部分。 在此记录下自己学习过程中的产物&#xff0c;以便于日后更有“收获感”。 后续还会继续完成其他章节的练习题题解。 正文 enums1 题目 // enums1.rs // // No hi…...

VPN简述

文章目录 VPNVPN基础VPN类型 VPN VPN隧道安全 VPN基础 背景&#xff1a; 在网络传输中&#xff0c;绝大部分数据内容都是明文传输&#xff0c;存在很多安全隐患&#xff08;窃听、篡改、冒充&#xff09; 总部、分公司、办事处、出差人员、合作单位等需要访问总部网络资源 Vi…...

【Kubernetes】常见面试题汇总(四十九)

目录 110.假设一家公司希望通过采用新技术来优化其工作负载的分配。公司如何有效地实现这种资源分配&#xff1f; 111.考虑一家拼车公司希望通过同时扩展其平台来增加服务器数量。您认为公司将如何处理服务器及其安装&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【…...

常见排序算法以及冒泡排序的基础使用方法

众所周知&#xff0c;冒泡排序是编程中最经典也是最简单的一种排序方法&#xff0c;它是通过重复访问对两个相邻的值进行比较&#xff0c;由于在互换的过程中&#xff0c;最大 (或最小) 的那个值会慢慢的交换到顶部&#xff0c;像汽水一样&#xff0c;故名“冒泡排序”。 let a…...

【网络安全】Cookie与ID未强绑定导致账户接管

未经许可,不得转载。 文章目录 前言正文前言 DigiLocker 是一项在线服务,旨在为公民提供一个安全的数字平台,用于存储和访问重要的文档,如 Aadhaar 卡、PAN 卡和成绩单等。DigiLocker 通过多因素身份验证(MFA)来保护用户账户安全,通常包括 6 位数的安全 PIN 和一次性密…...

Ansible Playbook原理与实践(Principles and Practice of Ansible Playbook)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…...

解决OpenCV保存视频 视频全部为绿色的bug

目录 项目场景&#xff1a; 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 项目场景&#xff1a; 使用OpenCV-Python 保存视频&#xff0c;视频为numpy array格式&#xff0c;保存的视频全部为无意义的绿色。 问题描述 用opencv 保存的视频会出现全部为绿色的情况&…...

手机使用指南:如何在没有备份的情况下从 Android 设备恢复已删除的联系人

在本指南中&#xff0c;您将了解如何从 Android 手机内存中恢复已删除的联系人。Android 诞生、见证并征服了 80% 的智能手机行业。有些人可能将此称为“非常大胆的宣言”&#xff0c;但最近的统计数据完全支持我们的说法。灵活性、高度改进的可用性和快速性是 Android 操作系统…...

TS系列(6):函数

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 TS系列&#xff08;1&#xff09;&#xff1a;TS是什么&#xff1f;如何使用&#xff1f; TS系列&#xff08;2&#xff09;&#xff1a;类型声明、类型推断和类型总览 TS系列&#xff08;3&#xff09;&…...

网盘能否作为FTP替代产品?企业该如何进行FTP国产化替代?

近年来&#xff0c;信创的概念引入和高效实践落地让更多的行业企业自发性地进行国产化替代&#xff0c;目前信创国产化替代还多发生在操作系统和应用层面&#xff0c;软件工具等目前还在下一阶段规划&#xff0c;但很多企业未雨绸缪&#xff0c;已经在做调研和尝试。 FTP作为世…...

Python操作MongoDB

一、Python链接MongoDB 1、安装pymongo包 使用包管理器安装 pip3 insatll pymongo 2、连接MongoDB 首先需要导入pymongo包&#xff1a; from pymongo import MongoClient 创建MongoClient对象&#xff1a; from pymongo import MongoClient #创建MongoClient对象&#…...

Redis --- 第二讲 --- 特性和安装

一、背景知识 Redis特性&#xff1a; Redis是一个在内存中存储数据的中间件&#xff0c;用于作为数据库&#xff0c;作为缓存&#xff0c;在分布式系统中能够大展拳脚。Redis的一些特性造就了现在的Redis。 在内存中存储数据&#xff0c;通过一系列的数据结构。MySQL主要是通…...

基于单片机的两轮直立平衡车的设计

本设计基于单片机设计的两轮自平衡小车&#xff0c;其中机械部分包括车体、车轮、直流电机、锂电池等部件。控制电路板采用STC12C5A60S2作为主控制器&#xff0c;采用6轴姿态传感器MPU6050测量小车倾角&#xff0c;采用TB6612FNG芯片驱动电机。通过模块化编程完成了平衡车系统软…...

网站编程技术 吉林出版集团股份有限公司/网站收录检测

mysql关闭的大致过程   1、The shutdown process is initiated     初始化关机过程有许多种方法1、mysqladmin shutdown ; 2、kill pid_of_mysqld   2、The server creates a shutdown thread if necessary     要不要创建这个线程取决于关闭操作的发起方式   3、…...

过年做啥网站能致富/上海全网推广

来自京东用户体验设计部&#xff08;JDC&#xff09;前端开发部的移动端 Vue 组件库&#xff0c;主要开发和服务于移动Web界面的企业级前中后台产品。 介绍 NutUI 1.0 版本于 2018 年发布&#xff0c;是一套来自京东用户体验设计部&#xff08;JDC&#xff09;前端开发部的移…...

福州网站制作培训/项目推广计划书

Android 中 Toast 的基本用法比较简单, 按照下面的文件复制运行即可. Toast 是一个消息提示组件 设置显示的位置 自定义显示内容 (示例: 添加一个图片) ToastUtil 类 ToastActivity 文件 package com.example.hello;import androidx.appcompat.app.AppCompatActivity;import an…...

项目建设管理 公司 网站/seo搜索引擎优化平台

2017-03-02在南方铝业(中国)有限公司精整车间1&#xff03;纵剪机列上&#xff0c;开卷张力是由气动抱闸控制的&#xff0c;通过压在开卷机铝卷材上的随动小压轮随着卷径的减小而下降&#xff0c;从而控制刹车气压使摩擦转矩正比于卷径&#xff0c;保持张力恒定。机列线速度的调…...

网站建设毕业设计心得/google浏览器入口

VLAN之间在二层是分隔开的&#xff0c;如果要实现VLAN之间的通信&#xff0c;必须要借助到三层路由功能。 支持VLAN间路由的设备&#xff1a;  1.任意的3层交换机  2.支持以太口起子接口的路由器   &#xff1c;单臂路由&#xff08;Router on a Stick&#xff09;&#xf…...

利趣网站开发商/重庆做优化的网络公司

利用createdElement标签创造一个option将文本栏里的内容加入value到option里&#xff0c;然后再用appendChild将option里的内容加到下拉框中&#xff0c;最后将文本框中的内容清空。 <!DOCTYPE html> <html><head><meta charset"UTF-8"><…...