C++模板编程

模板是泛型编程的基础,先给出泛型编程的概念。

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。

应用场景:比如要实现一个通用的,进行两个变量互相交换的函数,此时可以通过函数重载的方式,用不同的参数类型来实现该函数。但是是有缺陷的,因此也引出了模板编程。

1. 函数重载只是参数类型不同,当出现新类型的参数时,就要手动的再实现一份。

2. 代码的可维护性较低,一个出错可能导致所有的同名函数都出现问题。

模板是一个模具,通过用户传入的参数类型来生成对应类型的具体代码。本质是将重复的工作交给了编译器完成。

模板分为函数模板类模板

函数模板

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

template<typename T1, typename T2, ...., typename Tn>(此处的typename也可写作class)

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

函数模板是一个蓝图,它本身并不是函数,是编译器用使用特定方式产生具体类型函数的模具。

具体例子:

template<class T>
void Swap(T& num1, T& num2)
{std::swap(num1, num2);
}
template<typename T1, typename T2>
void PrintType(T1& val1, T2& val2)
{std::cout << typeid(val1).name() << std::endl;std::cout << typeid(val2).name() << std::endl;
}
int main()
{int a = 10, b = 20;Swap(a, b);std::cout << a << " " << b << std::endl;//20 10double c = 1.0;PrintType(a, c);//int, doublereturn 0;
}

函数模板原理

编译器编译阶段,编译器根据传入的实参类型来推演生成对应类型的函数以供调用。例如:当用int类型使用函数模板时,编译器通过对实参类型的推演,将T确定为int类型,然后产生一份专门处理int类型的代码。

函数模板实例化

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

函数模板的实例化又分为隐式实例化和显式实例化

隐式实例化

让编译器根据传入的参数类型自动进行参数类型的推演。

显式实例化

在函数名后的< >中指定模板参数的实际类型

例如vector<int> array;

模板参数匹配规则

(1)一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。

(2)对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模 板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板。

(3)模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。

类模板

类模板定义格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
//例子
template<class T>
class Base
{
public:
private:T _num;
};

类模板实例化

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

非类型模板参数

     模板参数分为类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

具体例子:

template<class T, size_t N = 10>
class Base
{
private:T _array[N];
};

注意: 1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。

            2. 非类型的模板参数必须在编译期就能确认结果。

模板特化

通常情况下,模板的使用可以实现与类型无关的代码,但有些特殊类型会得出错误的结果,此时需要对特殊类型进行特殊处理,称为模板特化。

函数模板的特化

具体例子:

class Base
{
public:int _left;int _right;
};
template<class T>
bool IsSame(T left, T right)
{return left == right;
}
template<>
bool IsSame<Base*>(Base* left, Base* right)//模板特化,对Base* 类型进行特殊处理
{return left->_left == right->_left && left->_right == right->_right;
}

函数模板的特化步骤:

1. 必须要先有一个基础的函数模板。

2. 关键字template后面接一对空的尖括号<>。

3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型。

4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。

类模板特化

类模板特化又分为全特化和偏特化

全特化就是将模板中的参数全都确定化。


template<class T1, class T2>
class Base
{
public:T1 _left;T2 _right;
};
template<>
class Base<char, int>
{
public:char _left;int _right;
};

偏特化:任何针对模版参数进一步进行条件限制设计的特化版本。

偏特化有两种表现形式,部分特化和进一步对参数进行限制

具体例子:


template<class T1, class T2>
class Base
{
public:T1 _left;T2 _right;
};
//部分特化
template<class T1>
class Base<T1, int>
{
public:T1 _left;int _right;
};
//对参数进行进一步限制
template<typename T1, typename T2>
class Base <T1*, T2*>//指针类型
{ 
public:T1 _d1;T2 _d2;
};

模板分离编译

分离编译:一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

模板是不支持声明和定义分离的。

原因:

C/C++程序要运行,是要经过 预编译->编译->汇编->链接 四个步骤的,其中预编译主要是进行文本处理,即宏替换,头文件的包含,以及注释的删除等;编译则是会对代码根据语言特性进行词法、语法、语义的分析,并形成汇编代码,同时对符号进行整合;汇编则是在此基础上,将汇编代码进一步翻译成二进制,同时形成符号表,链接时会将对应符号的地址填到符号表中,处理没有解决的地址问题。

而因为模板的声明和定义分离之后,编译器在编译时,会默认该模板函数的地址已经确定,所以只会在最后链接阶段,寻找相应模板函数的地址进行填表,但由于模板没有实例化,所以地址并不存在,所以链接阶段就会因为找不到对应的函数地址而报错。

解决方法:

建议将模板的声明和定义统一放到一个文件中,例如.hpp文件。

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

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

相关文章

【从浅学到熟知Linux】进程状态与进程优先级(含进程R/S/T/t/D/X/Z状态介绍、僵尸进程、孤儿进程、使用top及renice调整进程优先级)

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程及数据库等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 进程状态进程状态查看R运行状态&#xff08;running&#xff09;S睡眠状态&#xff08;sleeping&a…

蓝桥杯嵌入式速成

蓝桥杯嵌入式速成 cubmx创建工程利用官方提供的LCD代码创建工程&#xff08;15届不能用&#xff09;利用官方提供的LCD代码创建工程&#xff08;15届能用&#xff09;Keil配置头文件注意其他注意 LED闪烁 按键短按长按双击 LCD高亮行高亮字符 RTCADCI2Cuart接收发送 PWMDAC定时…

Vue.js------vue基础

1. 能够了解更新监测, key作用, 虚拟DOM, diff算法2. 能够掌握设置动态样式3. 能够掌握过滤器, 计算属性, 侦听器4. 能够完成品牌管理案例 一.Vue基础_更新监测和key 1.v-for更新监测 目标&#xff1a;目标结构变化, 触发v-for的更新 情况1: 数组翻转情况2: 数组截取情况3…

VIT论文阅读

论文地址&#xff1a;https://arxiv.org/pdf/2010.11929.pdf VIT论文阅读 摘要INTRODUCTION结论RELATEDWORKMETHOD1.VISIONTRANSFORMER(VIT)整体流程消融实验HEAD TYPE AND CLASSTOKENpoisitional embedding 整体过程公式Inductive biasHybrid Architecture 2.FINE-TUNINGANDH…

Substance 3D2024版 下载地址及安装教程

Substance 3D是Adobe公司推出的一套全面的3D设计和创作工具集合&#xff0c;用于创建高质量的3D资产、纹理和材质。 Substance 3D包括多个功能强大的软件和服务&#xff0c;如Substance 3D Painter、Substance 3D Designer和Substance 3D Sampler等。这些工具提供了广泛的功能…

TQ15EG开发板教程:在MPSOC上运行ADRV9009

首先需要在github上下载两个文件&#xff0c;本例程用到的文件以及最终文件我都会放在网盘里面&#xff0c; 地址放在最后面。在github搜索hdl选择第一个&#xff0c;如下图所示 GitHub网址&#xff1a;https://github.com/analogdevicesinc/hdl/releases 点击releases选择版…

vue实现海康h5player问题汇总

1. 引入问题 最开始写的时候&#xff0c;把h5player封装成了一个组件&#xff0c;把资源文件随便放在了一个目录下&#xff0c; 直接在子组件中引入&#xff0c;报错window.JSPlugin is not a constructor 或者JSPlugin is not defined 初步分析应该是引入资源文件失败&#x…

Java异常处理机制详解:多层方法调用与异常传播(day23)

1.数组下标越界 2.多个处理异常 上面这两个代码的区别就是有无 System.out.println("抛出了NumberFormatException"); System.out.println("抛出了ArrayIndexOutOfBoundsException"); 第一种是不论捕获到哪种异常&#xff0c;都只会调用e.printStack…

Asterisk 21.2.0编译安装经常遇到的问题和解决办法之pjproject

目录 Asterisk社区官方的说法然而买家秀是这样的pjproject-2.14下载不了的问题如何解决 Asterisk社区官方的说法 编译安装Asterisk 21.2.0版本 按照官网文档&#xff0c;原则上只需要如下几步&#xff1a; ./contrib/scripts/install_prereq install ./configure make make i…

Golang | Leetcode Golang题解之第20题有效的括号

题目&#xff1a; 题解&#xff1a; func isValid(s string) bool {n : len(s)if n % 2 1 {return false}pairs : map[byte]byte{): (,]: [,}: {,}stack : []byte{}for i : 0; i < n; i {if pairs[s[i]] > 0 {if len(stack) 0 || stack[len(stack)-1] ! pairs[s[i]] {…

【leetcode面试经典150题】36. 旋转图像(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

第04章 计算机常用通信指标和术语视频课程

4.1 本章目标 掌握bit、Byte、KB、MB、GB、TB概念和换算关系掌握波特率、比特率、误码率的概念掌握信道、基带信号、频带信号概念了解多路复用、频分多路复用、时分多路复用了解同步传输、异步传输概念 4.2 bit、Byte、KB、MB、GB、TB概念和换算关系 4.2.1 概念与换算 4.2.2…

docker-compose 之 OpenGauss

使用 docker 启动高斯数据库的示范脚本如下&#xff1a; docker-compose.yml version: 3.7 services:opengauss:image: enmotech/opengauss:5.1.0container_name: opengaussnetwork_mode: "host"privileged: truevolumes:- ./opengauss:/var/lib/opengaussenvironm…

使用自己的数据基于SWIFT微调Qwen-Audio-Chat模型

目录 使用自己的数据训练参数设置自己的数据准备语音转写任务语音分类任务 开始训练不同训练方法mpddpmp ddpdeepspeed 训练实例训练详情Qwen-Audio-Chat模型 模型数据实例官方可用的数据由内部函数处理为指定格式 训练好的模型测试 使用自己的数据 官方参考文档&#xff1a;…

CSPNet: A New Backbone that can Enhance Learning Capability of CNN

CSPNet 摘要1.引言3.方法3.1Cross Stage Partial NetworkDenseNetCross Stage Partial DenseNetPartial Dense BlockPartial Transition LayerApply CSPNet to Other Architectures 3.2 Exact Fusion ModelLooking Exactly to predict perfectlyAggregate Feature PyramidBalan…

【Android】【root remount】【3】remount 文件详细信息获取

前言 我们在root & remount 设备后&#xff0c;push相关文件到systm 、vendor、product 等目录进行调试&#xff0c;那么我们push的文件被保存在什么地方呢&#xff1f; 以及我们FWS、app侧如何过去push 的文件信息呢&#xff1f; remount push 文件保存 push 文件保存的…

java数据结构与算法刷题-----LeetCode684. 冗余连接

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 并查集 并查集 解题思路&#xff1a;时间复杂度O( n ∗ l o g 2…

高质量数据赋能大模型应用落地,景联文科技提供海量AI大模型数据

随着人工智能技术的迅猛进步&#xff0c;AI算法持续创新突破&#xff0c;模型的复杂度不断攀升&#xff0c;呈现出爆炸性的增长态势。数据的重要性愈发凸显&#xff0c;已然成为AI大模型竞争的核心要素。 Dimensional Research的全球调研报告显示&#xff0c;72%的受访者认为&a…

01、ArcGIS For JavaScript 4.29对3DTiles数据的支持

综述 Cesium从1.99版本开始支持I3S服务的加载&#xff0c;到目前位置&#xff0c;已经支持I3S的倾斜模型、3D Object模型以及属性查询的支持。Cesium1.115又对I3S标准的Building数据实现了加载支持。而ArcGIS之前一直没有跨越对3DTiles数据的支持&#xff0c;所以在一些开发过…

【Qt】:对话框(一)

对话框 一.基本的对话框二.自定义对话框三.通过图形化界面自定义对话框四.关于对话框mode 对话框是GUI程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口&#xff0c;出现在程序最上层&#xff0c;用于实现短期任务或者…