初识模板【C++】

P. S.:以下代码均在VS2022环境下测试,不代表所有编译器均可通过。
P. S.:测试代码均未展示头文件stdio.h的声明,使用时请自行添加。

  

在这里插入图片描述
                                           博主主页:LiUEEEEE
                                                C++专栏
                                              C语言专栏
                                            数据结构专栏
                                            排序算法专栏
                                         力扣牛客经典题目专栏

目录

  • 1、概念
  • 2、函数模板的实例化
    • 2.1 隐式实例化
    • 2.2 显式实例化:
  • 3、模板参数的匹配原则:
  • 4、类模板
    • 4.1 类模板的定义格式:
    • 4.2 类模板的实例化:
  • 5、结语

1、概念


  模板的概念是指在编译器中实现泛型编程,其目的是给予编译器一个模板,让其生成目标所需函数。

  例如,在日常代码中,如果需要交换不同类型的数据(例如 int char double),我们需要写三个交换函数,如下所示:

void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}void Swap(char& a, char& b)
{char tmp = a;a = b;b = tmp;
}void Swap(double& a, double& b)
{double tmp = a;a = b;b = tmp;
}

  此种写法十分繁琐,将相同率较高的代码重复书写,影响效率,故C++开辟了一个新赛道,将繁琐的工作交给编译器,使用者只需提供模板即可。

  模板的书写格式如下:
在这里插入图片描述
  因此,对于交换类型的函数,我们可以直接书写一个模板,让编译器自动生成其所需函数,例如:

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

  注意,此处的class 与 typename效果一样,在初学模板期间可不做区分。




2、函数模板的实例化


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

2.1 隐式实例化


  让编译器根据实参推演模板参数的实际类型,例如实现一个两数相加的函数模板,如下所示:
template <class T>
T add(const T& a, const T& b)
{return a + b;
}

  此时当我们传入参数为整形时,编译器会自动根据所传类型进行实例化,此时就叫做隐式实例化。

  但当我们所传类型为一个int 一个double时,就会发生报错,如下所示:
在这里插入图片描述
  当发生此种情况时,我们有两种方法:

  1. 用户自己进行强制类型转换,例如:
	cout << add(a, (int)c) << endl;cout << add((double)a, c) << endl;

2.使用显式实例化:如下一小标题内容所示。

2.2 显式实例化:


  在函数名后的<>中指定模板参数的实际类型
  例如上文中当传送一个int和一个double的情形,我们可以如下方式书写进行参数类型的指定:
	cout << add<int>(a, c) << endl;cout << add<double>(a, c) << endl;

  如果此时类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。




3、模板参数的匹配原则:


  一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数,例如:
// 专门处理int的加法函数
int Add(int left, int right)
{return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{return left + right;
}
void Test()
{Add(1, 2); // 与非模板函数匹配,编译器不需要特化Add<int>(1, 2); // 调用编译器特化的Add版本
}

  对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板,且模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。

  简而言之就是在同时存在同名的非模板函数和模板函数时,如果实现的目的相同,那么编译器将会自动选择匹配率更高的进行使用。



4、类模板


  

4.1 类模板的定义格式:

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

例如:

template<class T>
class Vector
{
public:Vector(size_t capacity = 10): _pData(new T[capacity]), _size(0), _capacity(capacity){}// 使用析构函数演示:在类中声明,在类外定义。~Vector();void PushBack(const T& data)void PopBack()// ...size_t Size() { return _size; }T& operator[](size_t pos){assert(pos < _size);return _pData[pos];}
private:T* _pData;size_t _size;size_t _capacity;
};

  类模板的目的旨在可以通过此类模板来应对不同类型数据的需求,例如顺序表,使用者可以使用类模板来分别创建不同数据类型的顺序表。

template <class T>
Vector<T>::~Vector()
{
if(_pData)
delete[] _pData;
_size = _capacity = 0;
}

  注意:类模板中函数放在类外进行定义时,需要加模板参数列表,并且不建议声明和定义分离,可能会造成链接过程中不必要的麻烦。

4.2 类模板的实例化:


  类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;




5、结语


在这里插入图片描述

  十分感谢您观看我的原创文章。
  本文主要用于个人学习和知识分享,学习路漫漫,如有错误,感谢指正。
  如需引用,注明地址。

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

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

相关文章

AV1技术学习:Intra Prediction

对于帧内预测模式编码块&#xff0c;亮度分量的预测模式和色度分量的预测模式在比特流中分别发出信号。亮度预测模式是基于相邻左侧和上侧两个编码块预测上下文的概率模型进行熵编码的。色度预测模式的熵编码取决于色度预测模式的状态。帧内预测以变换块为单位&#xff0c;并使…

Linux下文件I/O操作

读取 time.txt 文件&#xff0c;写入到time_2.txt 一、函数 1.1、open() 函数 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);…

RDMA 高性能架构基本原理与设计方案

在进行本文的学习学习之前&#xff0c;我们先对RDMA是什么做一个简单的科普与认识&#xff1a;一文带你了解什么是RDMA-CSDN博客 目录&#xff1a; 目录&#xff1a; 一、RDMA和传统网络方案的比较 1.1 传统网络方案&#xff1a; 1.1.1 缺点一&#xff1a;以太网卡&#xff0…

debian 更新源

前言 实现一键替换在线源 一键更新源 Debian 全球镜像站以下支持现有debian 11 12 echo "Delete the default source" rm -rf /etc/apt/sources.listecho "Build a new source" cat <<EOF>>/etc/apt/sources.list.d/debian.sources Types:…

Tensorflow入门实战 T09进行猫狗识别2

目录 1、前言 2、代码 3、运行结果 4、反思 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 1、前言 本周学习内容为&#xff0c;采用自己设置的vgg-16网络进行猫狗识别&#xff0c;使用的模型是YO…

自动驾驶三维车道线检测系列—LATR: 3D Lane Detection from Monocular Images with Transformer

文章目录 1. 概述2. 背景介绍3. 方法3.1 整体结构3.2 车道感知查询生成器3.3 动态3D地面位置嵌入3.4 预测头和损失 4. 实验评测4.1 数据集和评估指标4.2 实验设置4.3 主要结果 5. 讨论和总结 1. 概述 3D 车道线检测是自动驾驶中的一个基础但具有挑战性的任务。最近的进展主要依…

vscode搭建PyQt + Quick开发环境

VScode搭建PyQt Quick开发环境 目录 环境准备 &#x1f514;安装必要的Python包 &#x1f514;&#x1f50e; PyQt5和PySide2的区别&#x1f4be; 安装PyQt5&#x1f4be; 安装PySide2 配置VScode &#x1f514;&#x1f4bb; 安装扩展 代码示例 &#x1f514;✔ Python调用Qt…

【Django】django自带后台管理系统样式错乱,uwsgi启动css格式消失的问题

正常情况&#xff1a; ERROR&#xff1a;&#xff08;css、js文件加载失败&#xff09; 问题&#xff1a;CSS加载的样式没有了&#xff0c;原因&#xff1a;使用了django自带的admin&#xff0c;在使用 python manage.py runserver启动 的时候&#xff0c;可以加载到admin的文…

如何学习Spark:糙快猛的大数据之旅

作为一名大数据开发者,我深知学习Spark的重要性。今天,我想和大家分享一下我的Spark学习心得,希望能够帮助到正在学习或准备学习Spark的朋友们。 目录 Spark是什么?学习Spark的"糙快猛"之道1. 不要追求完美,在实践中学习2. 利用大模型作为24小时助教3. 根据自己的节…

无人机的发展前景大吗?

随着科技的飞速发展&#xff0c;无人机&#xff08;Unmanned Aerial Vehicle, UAV&#xff09;作为一种新兴的航空器&#xff0c;已逐渐从军事领域渗透到民用领域。无人机的应用广泛&#xff0c;包括但不限于航拍、物流配送、环境监测、农业植保、应急救援等多个领域。本文旨在…

Chromium CI/CD 之Jenkins实用指南2024-在Windows节点上创建任务(九)

1. 引言 在现代软件开发流程中&#xff0c;持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;已成为确保代码质量和加速发布周期的关键实践。Jenkins作为一款广泛应用的开源自动化服务器&#xff0c;通过其强大的插件生态系统和灵活的配置选项&#xf…

十七、【机器学习】【非监督学习】- K-均值 (K-Means)

系列文章目录 第一章 【机器学习】初识机器学习 第二章 【机器学习】【监督学习】- 逻辑回归算法 (Logistic Regression) 第三章 【机器学习】【监督学习】- 支持向量机 (SVM) 第四章【机器学习】【监督学习】- K-近邻算法 (K-NN) 第五章【机器学习】【监督学习】- 决策树…

静态代理与动态代理的区别与选择

在当今软件开发领域&#xff0c;代理模式作为一种重要的设计模式&#xff0c;广泛应用于增强现有对象功能、控制访问权限以及实现远程调用等场景。本文旨在深入探讨静态代理与动态代理之间的核心区别&#xff0c;帮助开发者理解两者在实现机制、灵活性、性能表现及适用场景上的…

Filebeat k8s 部署(Deployment)采集 PVC 日志发送至 Kafka——日志处理(二)

文章目录 前言Filebeat Configmap 配置Filebeat Deployment验证总结 前言 在上篇文章中总结了 Django 日志控制台输出、文件写入按天拆分文件&#xff0c;自定义 Filter 增加 trace_id 以及过滤——日志处理&#xff08;一)&#xff0c;将日志以 JSON 格式写入日志文件。我们的…

无人机侦察:二维机扫雷达探测设备技术详解

二维机扫雷达探测设备采用机械扫描方式&#xff0c;通过天线在水平方向和垂直方向上的转动&#xff0c;实现对目标空域的全方位扫描。雷达发射机发射电磁波信号&#xff0c;遇到目标后产生反射&#xff0c;反射信号被雷达接收机接收并处理&#xff0c;进而得到目标的位置、速度…

spring MVC 简单的案例(2)用户登录

一、用户登录 1&#xff09;前端代码 index.html <!doctype html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport"content"widthdevice-width, user-scalableno, initial-scale1.0, maxim…

git commit报错: pre-commit hook failed (add --no-verify to bypass)

原因&#xff1a; 在提交前做代码风格检查&#xff0c;若检查不通过&#xff0c;则提交失败 解决方案&#xff1a;进入项目的.git>hooks目录&#xff0c;找到pre-commit文件&#xff0c;删除即可

单周期CPU设计(二)取指模块(minisys)(verilog)(vivado)

timescale 1ns / 1ps // module Ifetc32 (input reset, // 复位信号(高电平有效)input clock, // 时钟(23MHz)output [31:0] Instruction, // 输出指令到其他模块output [31:0] PC_plus_4_out, // (pc4)送执行单元input [31:0] Add_result, // 来自执行单元,算出…

基于STC8H4K64TL单片机的触摸功能和数码管驱动功能实现一个触摸按键单击长按都增加数值另一个触摸按键单击长按都减少数值应用

基于STC8H4K64TL单片机的触摸功能和数码管驱动功能实现一个触摸按键单击长按都增加数值另一个触摸按键单击长按都减少数值应用 STC8H4K64TL单片机介绍STC8H4K64TL单片机管脚图(48个引脚)STC8H4K64TL单片机串口仿真与串口通信STC8H4K64TL单片机管脚图(32个引脚)STC8H4K64TL单…

【学习css3】使用flex和grid实现等高元素布局

过往的实现方法是使用浮动加计算布局来实现&#xff0c;当flex和grid问世时&#xff0c;这一切将变得简单起来 一、简单的两列实现 1、先看页面效果 2、css代码 .container {padding: 10px;width: 100ch;margin: 0 auto;box-shadow: inset 0 0 0 2px #ccc;}.column {margin: 2…