【C++】初识模板:函数模板和类模板

目录

一、模板函数

1、函数模板的概念

2、函数模板的格式

3、函数模板的原理

4、函数模板实例化

5、 模板参数的匹配原则

二、类模板 

1 、类模板的定义格式

2 、类模板的实例化

3、模板类示例


一、模板函数

1、函数模板的概念

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

2、函数模板的格式

模板函数通过在函数定义前使用关键字 “template” 和一个或多个模板参数来定义。模板参数可以是类型参数或非类型参数。类型参数是用于指定函数参数类型的通用标识符,非类型参数则是用于指定常量值或常量表达式。

下面是一个简单的模板函数示例:

template <class T>
T findMax(T a, T b) {
    return (a > b) ? a : b;
}

在上面的示例中,我们定义了一个名为 “findMax” 的模板函数。该函数接受两个类型相同的参数,并返回较大的那个参数。通过使用模板参数 “T”,我们可以在不同的上下文中使用相同的函数实现。

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

3、函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模 板就是将本来应该我们做的重复的事情交给了编译器

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

4、函数模板实例化

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

【1】、隐式实例化:让编译器根据实参推演模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int 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(a1, (int)d1);
	return 0;
}

 

【2】、显式实例化:在函数名后的 < > 中指定模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	//  使用显式实例化
	Add<int>(a1, d1);
	return 0;
}
【注意】:如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

5、 模板参数的匹配原则


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

// 专门处理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版本
}

【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】、模板函数不允许自动类型转换,但普通函数可以进行自动类型转换


二、类模板 

1 、类模板的定义格式

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

2 、类模板的实例化

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

3、模板类示例

模板类的定义类似于模板函数,需要使用关键字 “template” 和一个或多个模板参数来定义。模板参数可以是类型参数或非类型参数。类型参数用于指定类中的数据类型,非类型参数用于指定常量值或常量表达式。

下面是一个简单的模板类示例:

template <class T>
class Stack {
private:
    T* data;
    int top;
    int capacity;

public:
    Stack(int maxCapacity) {
        capacity = maxCapacity;
        data = new T[capacity];
        top = -1;
    }

    ~Stack() {
        delete[] data;
    }

    void push(T element) {
        if (top == capacity - 1) {
            throw std::overflow_error("Stack is full");
        }
        data[++top] = element;
    }

    T pop() {
        if (top == -1) {
            throw std::underflow_error("Stack is empty");
        }
        return data[top--];
    }

    bool isEmpty() {
        return (top == -1);
    }

    int size() {
        return top + 1;
    }
};

在上面的示例中,我们定义了一个名为 “Stack” 的模板类。它是一个栈数据结构的实现,可以用于存储各种类型的数据。通过使用模板参数 “T”,我们可以在不同的上下文中使用相同的类定义来创建具有不同数据类型的栈对象。

使用模板类时,我们需要在创建对象时指定具体的模板参数类型。例如:

int main() {
    Stack<int> intStack(10);
    Stack<double> doubleStack(20);

    intStack.push(5);
    doubleStack.push(3.14);

    intStack.pop();
    doubleStack.pop();

    return 0;
}

在上面的示例中,我们分别使用了整数和浮点数作为模板参数类型来创建了两个栈对象。通过这种方式,我们可以在不同的上下文中使用相同的类实现,提高代码的复用性和灵活性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【粉丝福利社】Flutter小白开发——跨平台客户端应用开发学习路线(文末送书-完结)

&#x1f3c6; 作者简介&#xff0c;愚公搬代码 &#x1f3c6;《头衔》&#xff1a;华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xf…

Bee+SpringBoot稳定的Sharding、Mongodb ORM功能(同步 Maven)

Hibernate/MyBatis plus Sharding JDBC Jpa Spring data GraphQL App ORM (Android, 鸿蒙) Bee 小巧玲珑&#xff01;仅 860K, 还不到 1M, 但却是功能强大&#xff01; V2.2 (2024春节・LTS 版) 1.Javabean 实体支持继承 (配置 bee.osql.openEntityCanExtendtrue) 2. 增强批…

项目学习记录

项目开发 创建项目环境配置关联git新增模块项目启动打印地址日志使用httpclient进行idea内部控制台测试使用AOP拦截器打印日志 创建项目 创建一个空项目&#xff0c;并勾选下面选项 然后进入pom.xml中修改项目配置 根据这个链接选则&#xff0c;修改项目的支持版本 链接&#…

猫头虎分享已解决Bug || CPU过载(CPU Overload):HighCpuUsageWarning, CpuOverloadException

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

vue3 之 商城项目—一级分类

整体认识和路由配置 场景&#xff1a;点击哪个分类跳转到对应的路由页面&#xff0c;路由传对应的参数 router/index.js import { createRouter, createWebHashHistory } from vue-router import Layout from /views/Layout/index.vue import Home from /views/Home/index.vu…

linux 06 磁盘管理

01.先管理vm中的磁盘&#xff0c;添加一个磁盘 只有这种方式才可以增加/dev/sd* 中的目录 例如会增加一个sdc 第一步.vm软件&#xff0c;打开虚拟机设置&#xff0c;添加硬盘 第二步.选择推荐scsi 第三步.创建一个新的虚拟磁盘 第四步. 第五步. 02.在创建好的vm虚拟机中查…

automative

car sevice car-lib

html5+css3胶囊按钮代码

效果 代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title></title> <style> /* 胶囊开关的样式 */ .switch { position: relative; display: inline-block; width: 6…

【leetcode热题100】最大矩形

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。 示例 1&#xff1a; 输入&#xff1a;matrix [["1","0","1","0","0"],["1",&quo…

文件绕过-Unsafe Fileuoload

文件上传基础 什么是文件上传 将客户端数据以文件形式封装通过网络协议发送到服务器端&#xff0c;在服务器端解析数据&#xff0c;最终在服务端硬盘上作为真实的文件保存。 通常一个文件以HTTP协议进行上传时&#xff0c;将以POST请求发送至Web服务器&#xff0c;Web服务器…

1987-2022年各省进出口总额数据整理(含进口和出口)(无缺失)

1987-2022年各省进出口总额数据整理&#xff08;含进口和出口&#xff09;&#xff08;无缺失&#xff09; 1、时间&#xff1a;1987-2022年 2、来源&#xff1a;各省年鉴、统计公报 3、指标&#xff1a;进出口总额&#xff08;万美元&#xff09;、进口总额&#xff08;万美…

2009-2019年地级市分类转移支付数据

2009-2019年地级市分类转移支付数据 1、时间&#xff1a;2009-2019年 2、来源&#xff1a;整理自wind 3、指标&#xff1a;公共财政收入:返还性收入、公共财政收入:一般性转移支付收入、公共财政收入:专项转移支付收入 4、范围&#xff1a;280个地级市 5、指标解释&#x…

Windows - URL Scheme - 在Windows上无管理员权限为你的程序添加URL Scheme

Windows - URL Scheme - 在Windows上无管理员权限为你的程序添加URL Scheme What 想不想在浏览器打开/控制你的电脑应用&#xff1f; 比如我在浏览器地址栏输入wegame://后回车会提示是否打开URL:wegame Portocol。 若出现了始终允许选项&#xff0c;你甚至可以写一个Web界面…

高效测试利器:Jmeter+Ant+Jenkins定时监控接口揭秘!

基于JmeterantJenkins的接口性能监控框架 Jenkins的安装和配置 简介 部署到持续集成平台可以实现脚本的定时运行&#xff0c;这是接口测试的核心。 这里我们选用了jenkins,jenkins是一个强大的持续集成系统&#xff0c;使用起来也很简单。 使用步骤如下&#xff1a; 1、 安装…

Redis核心技术与实战【学习笔记】 - 23.Redis 主从切换故障,有哪些坑

前言 Redis 的主从同步机制不仅可以让从库服务更多的读请求&#xff0c;分担主库的压力&#xff0c;而且还能在主库发生故障时&#xff0c;进行主从库切换&#xff0c;提供高可靠服务。 不过&#xff0c;在实际使用主从机制时会踩到一些“坑”&#xff1a;主从数据不一致、读…

保育员怎么搜题答案?用这5款神器就够了!!! #媒体#笔记#知识分享

专供大学生使用的搜题神器&#xff0c;支持拍照搜题、文字搜题、语音搜题等多种搜题方式&#xff0c;能快速找到课本习题的题目答案&#xff0c;而且还会附带详细的答案解析&#xff0c;加深我们对题目的理解。 1.大鱼搜题 这是一个公众号 适合大学生&#xff0c;基本上网课…

动漫风博客介绍页面源码

动漫风博客介绍页面源码&#xff0c;HTML源码&#xff0c;图片背景有淡入切换特效 蓝奏云&#xff1a;https://wfr.lanzout.com/iIDZu1nrmjve

清理神器CleanMyMac X 空间透镜——可视化您的磁盘空间 空间透镜有什么用

不久前&#xff0c;CleanMyMac X 发布了一个新功能&#xff1a; 空间透镜 相信有非常多的小伙伴和小编一样&#xff0c; 对这个功能一脸问号 这啥玩意儿&#xff1f;&#xff1f;&#xff1f; 今天就让我们深入了解一下&#xff0c; CleanMyMac X 的空间透镜功能。 - 更好…

【汇编】简单的linux汇编语言程序

一、Linux系统汇编语言 Linux系统上的汇编语言可以使用不同的语法风格&#xff0c;主要包括Intel语法和AT&T语法。这两种语法有各自的特点和风格区别&#xff0c;尽管它们表示的底层机器指令相同。下面分别对两种语法进行简要说明&#xff1a; Intel语法 Intel语法是由I…

《MySQL 简易速速上手小册》第10章:未来趋势和进阶资源(2024 最新版)

文章目录 10.1 MySQL 在云计算和容器化中的应用10.1.1 基础知识10.1.2 重点案例&#xff1a;使用 Python 部署 MySQL 到 Kubernetes10.1.3 拓展案例 1&#xff1a;在 AWS RDS 上部署 MySQL 实例10.1.4 拓展案例 2&#xff1a;使用 Docker 部署 MySQL 10.2 MySQL 和 NoSQL 的整合…
最新文章