C++ 函数模板与类模板
C++最重要的特性之一就是代码重用,为了实现代码重用,代码必须具有通用性。通用代码应不受数据类型的影响,并且可以自动适应数据类型的变化。这种程序设计类型称为参数化程序设计。模板是C++支持参数化程序设计的工具,通过它可以实现参数化多态性。所谓参数化多态性,就是将程序所处理的对象的类型参数化,使得一段程序可以用于处理多种不同类型的对象。
1.函数模板
通过函数重载,可以看出重载函数通常是对于不同的数据类型完成类似的操作。很多情况下,一个算法是可以处理多种数据类型的。但是用函数实现算法时,即使设计为重载函数也只是使用相同的函数名,函数体仍然要分别定义。
下面是两个求绝对值的函数:
int abs(int x)
{return x < 0 ? -x : x;
}double abs(double x)
{return x < 0 ? -x : x;
}
这两个函数只有参数类型和返回类型不同,功能完全一样。类似这样的情况,我们需要写一段通用的代码是用于多种不同的数据类型,这样会使代码的可重用性大大提高,从而提高软件的开发效率。使用函数模板就是为了达到这一目的。程序员只对函数模板编写一次,然后基于调用函数时提供的参数类型,C++编译器将自动产生相应的函数来正确地处理该类型的数据。
(1)函数模板的定义形式为
template <模板参数表>
类型名 函数名(参数表)
{函数体定义
}
所有函数模板的定义都是用关键字template开始的,该关键字之后是用尖括号<>括起来的“模板参数表”。模板参数表由用逗号隔开的模板参数构成,可以包括以下内容:
①class(或typedef)标识符,指明可以接收一个类型参数。这些类型参数代表的是类型,可以是内部类型或者自定义类型。
②“类型说明符”标识符,指明可以接收一个由“类型说明符”所规定类型的常量作为参数。
③template<参数表>class标识符,指明可以接收一个类模板名作为参数。
类型参数可以用来指定函数模板本身的形参类型、返回值类型,以及声明函数中的局部变量。函数模板中函数体的定义方式与定义普通函数类似。
【例1】求绝对值的函数模板
template<class T>
T abs(T x)
{return x < 0 ? -x : x;
}
int main()
{int n = -5;cout << abs(n) << endl;double m = -6.8;cout << abs(m) << endl;return 0;
}
运行结果:
分析:
①在上述主函数中调用abs()时,编译器从实参的类型推导出函数模板的类型参数。
②当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数,这一过程称为函数模板的实例化。
例如,对于调用表达式abs(n),由于实参n是int类型,所以推导出函数模板中类型参数T为int,接着,编译器以函数模板为样板,生成如下函数,该函数为函数模板abs的一个实例:
int abs(int x)
{return x < 0 ? -x : x;
}
同样,对于调用表达式abs(m),由于实参m是double型,所以推导出函数模板中类型参数T为double,接着,编译器以函数模板为样板,生成如下函数:
double abs(double x)
{return x < 0 ? -x : x;
}
③因此,当主函数第一次调用abs时,执行的实际上是由函数模板生成的函数int abs(int x);
,主函数第二次调用abs时,执行的实际上是由函数模板生成的函数double abs(double x);
。
【例2】函数模板示例
template<class T>
void outputA(const T* arr, int n)
{for (int i = 0;i < n; i++){cout << arr[i] << " ";}cout << endl;
}int main()
{const int A_n = 5;const int B_n = 6;const int C_n = 7;int arr[A_n] = { 1,2,3,4,5 };cout << "输出数组arr的内容:" << " ";outputA(arr, A_n);double brr[B_n] = { 1.1,2.2,3.3,4.4,5.5,6.6 };cout << "输出数组brr的内容:" << " ";outputA(brr, B_n);char crr[C_n] = "Hi yyn";cout << "输出数组crr的内容:" << " ";outputA(crr, C_n);return 0;
}
运行结果:
分析:
函数模板中声明了类型参数T,表示一种抽象的类型。当编译器检测到程序中调用函数模板outputA时,便用outputA的第一个实参的类型替换掉整个模板定义中的T,并建立用来输出指定类型数组的一个完整的函数,然后再编译这个新建的函数。
主函数中声明了3中不同类型的数组,int型数组arr,double型数组brr和char型数组crr,长度分别为5,6,7。然后调用函数模板生成相应的函数,最后在屏幕上输出每个数组。编译过程中针对3种数据类型生成的函数如下:
outputA(a,A_n);//适用于int类型的outputA模板函数
outputA(b,B_n);//适用于double类型的outputA模板函数
outputA(c,C_n);//适用于char类型的outputA模板函数
由上例可以看出,模板函数与重载密切相关。从函数模板产生的相关函数都是同名的,编译器用重载的方法调用相应的函数。另外函数模板本身也可以用多种方法重载。
(2)模板函数的使用形式和函数的本质区别
①函数模板本身在编译时不会生成任何目标代码,只有由模板生成的实例会生成目标代码。
②被多个源文件引用的函数模板,应当连同函数体一同放在头文件中,而不能像普通函数那样只将声明放在头文件中。
③函数指针也只能指向函数模板的实例,而不能指向函数模板本身。
2.类模板
使用类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、返回值或局部变量能取任意类型(包括系统预定义的和用户自定义的)。
类是对一组对象的公共性质的抽象,而类模板则是对不同类的公共性质的抽象,因此,类模板是属于更高层次的抽象。由于类模板需要一种或多种类型参数,所以类模板也常常称为参数化类。
(1)类模板声明的语法形式
template<模板参数表>
class 类名
{类成员声明;
};
其中类成员的声明方法和普通类的定义几乎相同,只是它的各个成员(数据成员和函数成员)中通常要用到模板的类型参数T。其中“模板参数表”的形式与函数模板中的“模板参数表”相同。
如果需要在类模板以外定义其成员函数,则要采用以下的形式:
template<模板参数表>
类型名 类名<模板参数标识符列表>::函数名(参数表)
一个类模板声明,其自身并不是一个类,它说明了类的一个家族,只有被其他代码引用时,类模板才根据引用的需要生成具体的类。类模板的实例化过程在程序中时隐藏的。
使用一个类模板建立对象时,应以如下形式声明:
模板名<模板参数表>对象名1,...,对象名n;
【例】类模板应用举例
在本例中,声明一个实现任意类型数据存取的类模板S,然后通过具体数据类型参数对类模板进行实例化,生成类,然后类在被实例化生成对象s1,s2,s3和d。
struct student//结构体student
{int id;//学号float avg;//平均分
};template<class T>//类模板:实现对任意类型数据进行存取
class S
{
private:T item;//用于存放任意类型的数据bool Isvalue;//标记item是否被存入
public:S();//默认构造函数T& getE();//提取数据函数void putE(const T& x);//存入数据函数
};template<class T>//默认构造函数的实现
S<T>::S():Isvalue(false){}template<class T>//提取数据函数的实现
T&S<T>::getE()
{ if (!Isvalue)//如果提取的是没有初始化的数据,则程序终止{cout << "数据不存在" << endl;exit(1);//使程序完全退出,返回到操作系统//参数可用来表示程序终止的原因,可以被操作系统接收}elsereturn item;//返回item中存放的数据
}template<class T>//存入函数的实现
void S<T>::putE(const T& x)
{Isvalue = true;//将Isvalue设置为true,表示item中已存入数值item = x;//将x的值存入item
}int main()
{S<int>s1, s2;//定义两个S<int>类对象s1和s2,其中数据成员item为int型s1.putE(3);//向对象s1中存入数据(初始化对象s1为3)s2.putE(-7);//向对象s2中存入数据(初始化对象s1为-7)cout << s1.getE() << " " << s2.getE() << endl;//输出对象s1和s2的数据成员student g = { 1000,23 };//定义student类型结构体变量的同时赋予初值S<student>s3;//定义S<student>类对象s3,其中数据成员item为student类型s3.putE(g);//向对象s3中存入数据(初始化对象s3)cout << "这个学生的id是" << s3.getE().id << endl;//输出对象s3的数据成员S<double>d;//定义S<double>类对象d,其中数据成员item为double类型cout << "检索对象d";cout << d.getE() << endl;//输出对象d的数据成员//由于对象d未经初始化,在执行函数d.getE()过程中导致程序终止return 0;
}
运行结果:
相关文章:

C++ 函数模板与类模板
C最重要的特性之一就是代码重用,为了实现代码重用,代码必须具有通用性。通用代码应不受数据类型的影响,并且可以自动适应数据类型的变化。这种程序设计类型称为参数化程序设计。模板是C支持参数化程序设计的工具,通过它可以实现参…...

Tailwind CSS:简洁高效的工具,提升前端开发体验
112. Tailwind CSS:简洁高效的工具,提升前端开发体验 1. 什么是Tailwind CSS? Tailwind CSS是由Adam Wathan、Jonathan Reinink、David Hemphill和Steve Schoger等人共同创建的一种现代CSS框架。与传统的CSS框架不同,Tailwind CS…...

NR CSI(六) CSI reporting using PUCCH
之前NR CSI(二) the workflow of CSI report有对CSI report的相关流程进行介绍,而这篇主要看下CSI reporting over PUCCH的相关规定。 CSI report在PUCCH上传输的场景如上表红色字体,有三种场景,具体的对应的是Periodic 和Semi-Persistent CS…...

论文阅读---《Unsupervised Transformer-Based Anomaly Detection in ECG Signals》
题目:基于Transformer的无监督心电图(ECG)信号异常检测 摘要 异常检测是数据处理中的一个基本问题,它涉及到医疗感知数据中的不同问题。技术的进步使得收集大规模和高度变异的时间序列数据变得更加容易,然而ÿ…...
5G上行干扰规避的参数策略
LNR干扰避让 1. 干扰避让特性 D1/D2干扰避让:干扰与非干扰带宽独立测量,避免部分频带受干扰拉低整个带宽MCS,基于测量结果, 用户级自适应调度60/80/100M,躲避干扰频带。 窄带干扰避让:避免部分带宽的干扰对…...

CTF流量题解tcp1
用流量工具进行分析。发现消息长度有点异常。右键TCP跟踪。 ....mos.-mos-.-.mos-.-mos..-.mos..-mos-. 摩斯密码生成-网页工具 (adminun.com)...

Django快速入门
文章目录 一、安装1.创建虚拟环境(virtualenv和virtualenvwrapper)2. 安装django 二、改解释器三、创建一个Django项目四、项目目录项目同名文件夹/settings.py 五、测试服务器启动六、数据迁移七、创建应用八、基本视图1. 返回响应 response2. 渲染模板…...
Python “牵手” 淘宝商品详情数据获取方法,淘宝API申请指南
淘宝详情接口 API 是淘宝开放平台提供的一种 API 接口,它可以帮助开发者获取淘宝商品的详细信息,包括商品的标题、描述、图片等信息。在淘宝电商平台的开发中,淘宝详情接口 API 是非常常用的 API,因此本文将详细介绍淘宝详情接口 …...
OpenScene
paper:OpenScene: 3D Scene Understanding with Open Vocabularies code: https://github.com/pengsongyou/openscene 摘要:传统的3D场景理解方法依赖于带标签的3D数据集,在有监督的情况下为单个任务训练模型。我们提出了OpenScene,一种替代性的方法,模型预测CLIP特征空…...

HDFS中的Trash垃圾桶回收机制
Trash垃圾桶回收机制 文件系统垃圾桶背景功能概述Trash Checkpoint Trash功能开启关闭HDFS集群修改core-site.xml删除文件到trash删除文件跳过从trash中恢复文件清空trash 文件系统垃圾桶背景 回收站(垃圾桶)是windows操作系统里的一个系统文件夹&#…...

segment-anything使用说明
文章目录 一. segment-anything介绍二. 官网Demo使用说明三. 安装教程四. python调用生成掩码教程五. python调用SAM分割后转labelme数据集 一. segment-anything介绍 Segment Anything Model(SAM)根据点或框等输入提示生成高质量的对象遮罩,…...

在魔塔社区搭建通义千问-7B(Qwen-7B)流程
复制以下语句 python3 -m venv myvenvsource myvenv/bin/activatepip install modelscope pip install transformers_stream_generator pip install transformers pip install tiktoken pip install accelerate pip install bitsandbytestouch run.py vi run.py复制下面代码粘…...

Redis 加入服务列表自启动
1、下载reids windows版本,选择zip格式下载 2、解压zip,并进入路径; 3、命令提示符(cmd) 进入解压后的路径后,输入指令:redis-server --service-install redis.windows.conf; 4、如…...

MyCat管理及监控——zookeeper及MyCat-web安装
1.MyCat管理 2.MyCat-eye 3.zookeeper安装 第一步:解压 第二部: 切换目录,创建data文件夹 第三步:修改zookeeper配置文件 这样zookeeper安装及配置就完成了 4.MyCat-web安装 注意mycat-web要与zookeeper关联,…...

基于spring boot的餐饮管理系统java酒店饭店菜谱 jsp源代码mysql
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于spring boot的餐饮管理系统j 系统1权限ÿ…...

JVM分析工具JProfiler介绍及安装
目录 一、什么是JProfiler? 二、JProfiler 功能结构 1、分析代理 2、记录数据 3、快照 三、安装 一、什么是JProfiler? JProfiler是一个专业的工具,用于分析运行中的JVM内部发生的事情。当您的生产系统出现问题时,您可以…...
Nginx使用多个.conf文件配置虚拟主机server
使用 Nginx 配置多个虚拟机 server 服务。通常做法可以直接在 nginx.conf 文件中添加即可,如下事例: # nginx.confworker_processes 1;events {worker_connections 1024; }http {include mime.types;default_type application/octet-stream…...

nginx编译以及通过自定义生成证书配置https
1. 环境准备 1.1 软件安装 nginx安装编译安装以及配置https,需要gcc-c pcre-devel openssl openssl-devel软件。因此需要先安装相关软件。 yum -y install gcc-c pcre-devel openssl openssl-devel wgetopenssl/openssl-devel:主要用于nginx编译的htt…...

OpenAI 已为 GPT-5 申请商标,GPT-4 发布不到半年,GPT-5 就要来了吗?
据美国专利商标局(USPTO)信息显示,OpenAI已经在7月18日申请注册了“GPT-5”商标。 在这份新商标申请中,OpenAI将“GPT-5”描述为一种“用于使用语言模型的可下载计算机软件”。 继GPT-4发布之后,它预计将成为OpenAI下一…...

【Linux】深入理解进程概念
个人主页:🍝在肯德基吃麻辣烫 我的gitee:Linux仓库 个人专栏:Linux专栏 分享一句喜欢的话:热烈的火焰,冰封在最沉默的火山深处 文章目录 前言浅谈进程概念1. 进程和操作系统的联系2.描述进程的对象——PCB …...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...