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

【C++】泛型编程 ④ ( 函数模板 与 普通函数 调用规则 | 类型自动转换 | 类型自动转换 + 显式指定泛型类型 )

文章目录

  • 一、普通函数 与 函数模板 的调用规则 - 类型自动转换
    • 1、函数模板和重载函数
    • 2、类型自动转换
    • 3、代码示例 - 类型自动转换
  • 二、普通函数 与 函数模板 的调用规则 - 类型自动转换 + 显式指定泛型类型
    • 1、类型自动转换 + 显式指定泛型类型
    • 2、代码示例 - 类型自动转换 + 显式指定泛型类型






一、普通函数 与 函数模板 的调用规则 - 类型自动转换




1、函数模板和重载函数


定义了 函数模板 , 该 函数模板 可以接收 任意类型的参数 T , 但是要求这两个参数类型 T 和 返回值类型 T 必须是相同的 ;

// 使用 template 关键字 声明函数模板 
// 告诉 C++ 编译器 开始使用 泛型编程 
// 定义的 T 是泛型类型 
// 声明了多个泛型, 可以只使用其中的部分类型
// 使用函数模板时 , 显式类型调用 必须 显式指定所有 泛型类型 的实际类型
template <typename T>
T add(T a, T b) {cout << "调用函数模板 T add(T a, T b)" << endl;return a + b;
}

此外还定义了 函数模板 的 重载函数 , 该重载函数 接收两个 int 类型的参数 , 同时返回 int 类型的返回值 ;

// 函数模板的 重载函数
// 重载是发生在 同一个作用域中
// 重写是发生在 父类 与 子类 之间
// C++ 编译器优先 调用 符合要求的 普通函数
// 如果普通函数不符合要求 , 则考虑调用 函数模板
int add(int a, int b) {cout << "调用普通函数 int add(int a, int b)" << endl;return a + b;
}

2、类型自动转换


当 函数模板 有 重载的 普通函数时 , 普通函数 调用 优先级 高于 函数模板 ;

函数模板 会进行 严格类型匹配 , 不会进行 类型转换 ;

普通函数 如果 遇到 参数不匹配的情况 , 会将 函数参数 进行类型自动转换 ;


函数模板 与 普通函数 在 类型自动转换 方面调用规则如下 :

  • 首先 , 如果 符合 普通函数类型参数要求 , 优先调用普通函数 ;
  • 然后 , 如果 没有 符合要求的 普通函数 , 则查看 模板函数 能否匹配 ;
  • 最后 , 如果 模板函数 仍不能匹配 , 则查看 普通函数 类型转换能否匹配 ;

3、代码示例 - 类型自动转换


代码示例 :

#include "iostream"
using namespace std;// 使用 template 关键字 声明函数模板 
// 告诉 C++ 编译器 开始使用 泛型编程 
// 定义的 T 是泛型类型 
// 声明了多个泛型, 可以只使用其中的部分类型
// 使用函数模板时 , 显式类型调用 必须 显式指定所有 泛型类型 的实际类型
template <typename T>
T add(T a, T b) {cout << "调用函数模板 T add(T a, T b)" << endl;return a + b;
}// 函数模板的 重载函数
// 重载是发生在 同一个作用域中
// 重写是发生在 父类 与 子类 之间
// C++ 编译器优先 调用 符合要求的 普通函数
// 如果普通函数不符合要求 , 则考虑调用 函数模板
int add(int a, int b) {cout << "调用普通函数 int add(int a, int b)" << endl;return a + b;
}// 普通函数  调用 优先级 高于 函数模板
// 函数模板 会进行 严格类型匹配 , 不会进行 类型转换 ; 
// 
// 如果 符合 普通函数类型参数要求 , 优先调用普通函数 ; 
// 如果 没有 符合要求的 普通函数 , 则查看 模板函数 能否匹配 ; 
// 如果 模板函数 仍不能匹配 , 则查看 普通函数 类型转换能否匹配 ; int main() {int a = 10, b = 20; char x = 'A', y = 'B';// 调用普通函数// 如果符合普通函数要求 优先调用普通函数int c = add(a, b);cout << "c = " << c << endl;// 调用 函数模板// 普通函数类型不匹配, 查看 模板函数 能否匹配// 模板函数可以匹配int d = add(x, y);cout << "d = " << d << endl;// 调用 普通函数// 普通函数类型不匹配, 查看 模板函数 能否匹配// 模板函数不可以匹配 , 继续查看 普通函数 类型自动转换// x 可以转为 int 类型 , 这样就可以符合普通函数参数要求int e = add(a, x);cout << "e = " << e << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
}

执行结果 :

调用普通函数 int add(int a, int b)
c = 30
调用函数模板 T add(T a, T b)
d = -125
调用普通函数 int add(int a, int b)
e = 75
请按任意键继续. . .

在这里插入图片描述





二、普通函数 与 函数模板 的调用规则 - 类型自动转换 + 显式指定泛型类型




1、类型自动转换 + 显式指定泛型类型


在上面示例的前提下 , 如果 传入参数 类型分别是 int 和 char , 并且强行指定 泛型类型 , 这样必须使用函数模板 , 此时 函数模板 也可以进行 类型自动转换 ;

	int a = 10, b = 20; char x = 'A', y = 'B';// 调用 函数模板// 函数模板 显式类型调用 , 强行使用 函数模板int k = add<int>(a, x);cout << "k = " << k << endl;

2、代码示例 - 类型自动转换 + 显式指定泛型类型


代码示例 :

#include "iostream"
using namespace std;// 使用 template 关键字 声明函数模板 
// 告诉 C++ 编译器 开始使用 泛型编程 
// 定义的 T 是泛型类型 
// 声明了多个泛型, 可以只使用其中的部分类型
// 使用函数模板时 , 显式类型调用 必须 显式指定所有 泛型类型 的实际类型
template <typename T>
T add(T a, T b) {cout << "调用函数模板 T add(T a, T b)" << endl;return a + b;
}// 函数模板的 重载函数
// 重载是发生在 同一个作用域中
// 重写是发生在 父类 与 子类 之间
// C++ 编译器优先 调用 符合要求的 普通函数
// 如果普通函数不符合要求 , 则考虑调用 函数模板
int add(int a, int b) {cout << "调用普通函数 int add(int a, int b)" << endl;return a + b;
}// 普通函数  调用 优先级 高于 函数模板
// 函数模板 会进行 严格类型匹配 , 不会进行 类型转换 ; 
// 
// 如果 符合 普通函数类型参数要求 , 优先调用普通函数 ; 
// 如果 没有 符合要求的 普通函数 , 则查看 模板函数 能否匹配 ; 
// 如果 模板函数 仍不能匹配 , 则查看 普通函数 类型转换能否匹配 ; int main() {int a = 10, b = 20; char x = 'A', y = 'B';// 调用普通函数// 如果符合普通函数要求 优先调用普通函数int c = add(a, b);cout << "c = " << c << endl;// 调用 函数模板// 普通函数类型不匹配, 查看 模板函数 能否匹配// 模板函数可以匹配int d = add(x, y);cout << "d = " << d << endl;// 调用 普通函数// 普通函数类型不匹配, 查看 模板函数 能否匹配// 模板函数不可以匹配 , 继续查看 普通函数 类型自动转换// x 可以转为 int 类型 , 这样就可以符合普通函数参数要求int e = add(a, x);cout << "e = " << e << endl;// 调用 函数模板// 函数模板 显式类型调用 , 强行使用 函数模板int k = add<int>(a, x);cout << "k = " << k << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
}

执行结果 :

调用普通函数 int add(int a, int b)
c = 30
调用函数模板 T add(T a, T b)
d = -125
调用普通函数 int add(int a, int b)
e = 75
调用函数模板 T add(T a, T b)
k = 75
请按任意键继续. . .

在这里插入图片描述

相关文章:

【C++】泛型编程 ④ ( 函数模板 与 普通函数 调用规则 | 类型自动转换 | 类型自动转换 + 显式指定泛型类型 )

文章目录 一、普通函数 与 函数模板 的调用规则 - 类型自动转换1、函数模板和重载函数2、类型自动转换3、代码示例 - 类型自动转换 二、普通函数 与 函数模板 的调用规则 - 类型自动转换 显式指定泛型类型1、类型自动转换 显式指定泛型类型2、代码示例 - 类型自动转换 显式指…...

基于ChatGPT的文本生成艺术框架—WordArt Designer

WordArt Designer是一个基于gpt-3.5 turbo的艺术字生成框架&#xff0c;包含四个关键模块:LLM引擎、SemTypo、Styltypo和TextTypo模块。由gpt-3.5 turbo驱动的LLM引擎可以解释用户输入&#xff0c;从而将抽象概念转化为具体的设计。 SemTypo模块使用语义概念优化字体设计&…...

服务名无效。 请键入 NET HELPMSG 2185以获得更多的帮助

遇到的问题是MySQL服务没有。 因为net start 服务名&#xff0c;启动的是win下注册的服务。此时&#xff0c;我系统中并没有注册mysql到服务中。即下面没有mysql服务。 mysqld --install net start mysql...

UE5——C++编译MSB3073报错

报错&#xff1a; C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Microsoft\VC\v170\Microsoft.MakeFile.Targets(50,5): error MSB3073: 命令“D:\0_Game\EpicGame\UE_5.1\Engine\Build\BatchFiles\Rebuild.bat DigitalVisualizationEditor Win64 Deve…...

自己动手实现一个深度学习算法——六、与学习相关的技巧

文章目录 1.参数的更新1&#xff09;SGD2&#xff09;Momentum3&#xff09;AdaGrad4&#xff09;Adam5&#xff09;最优化方法的比较6&#xff09;基于MNIST数据集的更新方法的比较 2.权重的初始值1&#xff09;权重初始值不能为02&#xff09;隐藏层的激活值的分布3&#xff…...

Maven间接依赖

目录 背景 依赖标签 依赖的作用域 Maven仲裁机制 场景示例 多个pom树合并打包...

Java架构师分布式搜索数据准确性解决方案

目录 1 Elasticsearch内置分词器1.1 Standard(标准分词器)1.2 Simple(简单分词器)1.3 Whitespace(空格分词器)1.4 Stop(停止分词器)1.5 Keyword(关键字分词器)1.6 Pattern(模板分词器)1.7 Language(语言分词器)1.8 Fingerprint(指纹分词器)2 Es 模糊查询 match…...

Clickhouse学习笔记

学习内容参考&#xff1a;一套上手ClickHouse-OLAP分析引擎&#xff0c;囊括Prometheus与Grafana_哔哩哔哩_bilibili 下为笔记链接&#xff0c;以及全套笔记pdf版本 Clickhouse学习笔记&#xff08;1&#xff09;—— ClickHouse的安装启动_clickhouse后台启动_THE WHY的博客-C…...

vim——“Linux”

各位CSDN的uu们好呀&#xff0c;今天&#xff0c;小雅兰的内容是Linux的开发工具——vim。下面&#xff0c;我们一起进入Linux的世界吧&#xff01;&#xff01;&#xff01; Linux编辑器-vim使用 vim的基本概念 vim的基本操作 vim正常模式命令集 vim末行模式命令集 vim操…...

【QT深入理解】QT中的几种常用的排序函数

第一章&#xff1a;排序函数的概述 排序函数是一种在编程中常用的函数&#xff0c;它可以对一个序列&#xff08;如数组&#xff0c;列表&#xff0c;向量等&#xff09;中的元素进行排序&#xff0c;使其按照一定的顺序排列。排序函数可以根据不同的排序算法&#xff0c;如冒…...

自压缩llm 为 超长记忆

自压缩llm 为 超长记忆 解释数据处理实际例子解释 # 自压缩llm 为 超长记忆 # prompt 格式 # <|细颗粒词表|><|粗颗粒词表|><|细颗粒词表|> # 细颗粒词表 = 词1,词2,词3,词4,词5,词6,词7,词8,词9,词10, # 组颗粒词表id1, 组颗粒词表id2, 组颗粒…...

Perl的LWP::UserAgent库爬虫程序怎么写

Perl的LWP::UserAgent库是一个用于发送HTTP请求的Perl模块。它可以用于编写Web爬虫、测试Web应用程序、自动化Web操作等。以下是一个简单的使用LWP::UserAgent库发送HTTP GET请求的Perl脚本的例子&#xff1a; #!/usr/bin/perluse strict; use warnings; use LWP::UserAgent;# …...

【算法】算法题-20231116

这里写目录标题 一、合并两个有序数组&#xff08;力扣88 &#xff09;二、剑指 Offer 39. 数组中出现次数超过一半的数字三、移除元素&#xff08;力扣27&#xff09;四、找出字符串中第一个匹配项的下标&#xff08;28&#xff09; 一、合并两个有序数组&#xff08;力扣88 &…...

微软允许OEM对Win10不提供关闭Secure Boot

用户可能将无法在Windows 10电脑上安装其它操作系统了&#xff0c;微软不再要求OEM在UEFI 中提供的“关闭 Secure Boot”的选项。 微软最早是在Designed for Windows 8认证时要求OEM的产品必须支持UEFI Secure Boot。Secure Boot 被设计用来防止恶意程序悄悄潜入到引导进程。问…...

海康G5系列(armv7l) heop模式下交叉编译Qt qmqtt demo,出现moc缺少高版本GLibc问题之解决

1.编辑源 sudo vi /etc/apt/sources.list 2.添加高版本的源 deb http://th.archive.ubuntu.com/ubuntu jammy main #添加该行到文件 3.运行升级 sudo apt update sudo apt install libc6 4.strings /**/libc.so.6 |grep GLIBC_ 参考链接&#xff1a;version GLIBC_2.3…...

gRPC协议详解

gRPC介绍 gRPC是一个高性能、开源和通用的RPC&#xff08;远程过程调用&#xff09;框架&#xff0c;由Google发起并开发&#xff0c;于2015年对外发布。它基于HTTP/2协议和Protocol Buffers设计&#xff0c;支持多种编程语言&#xff08;如C、Java、Python、Go、Ruby、C#、No…...

虹科方案 | 从概念到生产的自动驾驶软件在环(SiL)测试解决方案

来源&#xff1a;雅名特自动驾驶 虹科方案 | 从概念到生产的自动驾驶软件在环&#xff08;SiL&#xff09;测试解决方案 自动驾驶软件在环&#xff08;SiL&#xff09;测试解决方案 自动驾驶软件在环&#xff08;SiL&#xff09;测试解决方案能够研究和验证高历程实验和恶劣驾…...

demo(二)eurekaribbon----服务注册、提供与消费

前一篇实现了服务注册中心的搭建&#xff0c;并提供服务注册到注册中心上。在之前的基础上&#xff0c;实现服务消费。 一、相关介绍 1、RestTemplate工具 2、LoadBalanced注解 二、ribbon示例&#xff1a; 先启动eureka-service注册中心&#xff0c;再将eureka-client修改…...

2023年09月 Python(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 阅读以下代码,程序输出结果正确的选项是?( ) def process_keywords(keywords_list):unique_keywords = list(set(keywords_list))...

python3.8 安装 ssl 模块 和 _ctypes 模块

这文章目录 前情提要安装 openssl-1.1.1重新编译安装 python3.8-rpath 编译选项介绍python3.8 跟 python3.10 的区别那要怎么解决这个问题呢&#xff0c;我想到有四种解决方案&#xff1a; 前情提要 我在之前给 python3.10 安装 ssl 模块后以为该步骤 “对于 python3.6、pytho…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...