C++中的函数重载

函数重载是指在同一个作用域(通常是一个类或者一个命名空间)内,可以有多个同名函数,但是这些同名函数的参数列表(参数的个数、类型或者顺序)不同。当调用这个函数名时,编译器会根据传入的实际参数的类型、个数和顺序等来确定具体调用哪一个重载函数。

函数重载主要用于提供一组功能相似但参数类型或参数数量不同的函数,这样可以让代码更加灵活和易读。

函数重载的作用: 函数名可以相同,提高复用性

函数重载满足的条件:

1.同一作用域下(全局,类内,结构体内,命名空间)

2.函数名称相同

3.函数参数类型不同或者个数不同或者顺序不同

例如下面的代码就是函数重载:

//函数重载需要函数在同一个作用域下
void func()
{cout << "func的调用!" << endl;
}
void func(int a)
{cout << "func(int a)的调用!" << endl;
}
void func(double a)
{cout << "func(double a)的调用!" << endl;
}
void func(int a,double b)
{cout << "func(int a,double b)的调用!" << endl;
}
void func(double a,int b)
{cout << "func(double a,int b)的调用!" << endl;
}
//函数返回值不可以作为函数重载条件
/*int fun(double a, int b)
{cout << "func(double a,int b)的调用!" << endl;
}*/
int main()
{func();//func的调用!func(10);//func(int a)的调用!func(3.14);//func(double a)的调用!func(10, 3.14);//func(int a,double b)的调用!return 0;
}

注意:函数的返回值不可以作为函数重载的条件,函数重载与返回值无关

原因:

1.编译阶段的不确定性

函数调用时,编译器在解析函数调用代码(在编译阶段)时,主要关注的是函数的参数,而不是函数的返回值。因为在很多情况下,函数的返回值可能不会被立即使用。例如下面,当调用func(5)时,编译器不知道应该调用返回void的func函数还是返回int的func函数,因为它无法根据这个调用语句本身确定用户是否会使用返回值。

void func(int a);
int func(int a);
int main() {func(5);  // 这里编译器无法确定调用哪一个func函数return 0;
}

2.函数调用的语义冲突

函数调用的主要目的是执行一系列操作(通过函数体中的代码),并且可能会对传入的参数进行修改或者利用参数完成一些计算等。如果仅以返回值来区分函数重载,会导致代码的逻辑混乱。比如,在一些复杂的表达式中,函数的返回值可能会被忽略或者被用于其他隐式转换等情况,这使得编译器很难准确地判断应该调用哪一个函数。例如,考虑一个函数可能返回一个指针或者一个整数,在表达式if (func(3))中,如果可以根据返回值重载func,编译器很难确定这里期望的是指针类型的返回值用于条件判断(可能检查指针是否为NULL)还是整数类型的返回值用于条件判断(非零为真,零为假)。

为什么C不可以重载,而C++可以重载:

因为C++把函数编译完之后,会在名字后面加上类型的标识来区分不同的重载函数,而C语言不会

函数重载注意事项:

1.引用作为重载条件 2.函数重载碰到函数默认参数

1.引用作为重载条件

引用在作为函数参数时,可以作为函数重载的条件。因为引用本质上是对象的别名,不同类型的引用在参数传递时表现出不同的特性。

对于func(int& a),它接受一个可修改的左值引用。当传递x时,因为x是一个普通的非const变量,它可以被修改,所以调用这个函数,函数内部可以修改x的值。对于func(const int& a),它接受一个const引用。当传递y(y是const变量)时,调用这个函数,函数内部不能修改y的值。这样通过引用的类型(const与否)实现了函数重载,使得程序可以根据参数是否为const来选择合适的函数版本。


void func(int& a) {a = 10;cout << a << endl;
}
void func(const int& a) {cout << "不能修改a的值" << endl;
}
int main() {int x = 5;const int y = 7;func(x);     //调用void func(int& a)  //10func(y);     //调用void func(const int& a) //不能修改a的值return 0;
}

2.函数重载碰到函数默认参数

潜在的二义性问题:当函数重载和函数默认参数同时出现时,可能会导致编译器无法确定调用哪一个函数的情况,即产生二义性。

当调用func(5)时,编译器不知道应该调用带有一个参数的func(int a)还是调用带有两个参数且第二个参数有默认值的func(int a, int b = 0)。因为这两种情况在语法上都有可能匹配这个函数调用,所以编译器会产生错误提示,需要程序员明确函数调用意图或者修改函数重载和默认参数的设置来避免这种二义性。

void func(int a, int b = 0);
void func(int a);
int main() {func(5);  // 这里编译器会报错,产生二义性return 0;
}

函数重载的实现原理

1.名字修饰

在编译阶段,编译器会对重载函数的名字进行改编(名字修饰)。名字修饰是一种机制,它根据函数的参数类型,参数数量等信息来生成一个唯一的内部名称。

例如在 C++ 中,编译器可能会把函数名和参数信息编码成一个复杂的符号,编译器可能会将int add(int a, int b)修饰为类似_add_int_int(这只是一个简单示意,实际的名字修饰规则因编译器而异),int add(int a, int b, int c)可能修饰为_add_int_int_int,float add(float a, float b)可能修饰为_add_float_float。当程序调用一个重载函数时,编译器会根据实际传入的参数类型和数量等信息,查找经过名字修饰后的函数名称,从而确定要调用的具体函数实现。这种机制使得编译器能够在链接阶段或者运行时(取决于具体的语言实现和调用方式)准确地找到正确的函数版本。

2.类型匹配和最佳匹配原则

当发生函数调用时,编译器会检查传入的实际参数类型,并与所有重载函数的参数类型列表进行比较。它会寻找最匹配的函数版本。

例如,如果调用add(1, 2),编译器会发现int add(int a, int b)这个函数版本是最匹配的,因为传入的参数是两个整数,与这个函数的参数类型完全一致。如果存在多种可能的匹配情况,编译器会根据一些规则来确定最佳匹配。例如,可能会考虑是否存在完全匹配、是否需要进行隐式类型转换等因素。如果有一个函数调用add(1.0f, 2.0f),编译器会选择float add(float a, float b),因为这是参数类型完全匹配的情况,而不是选择需要进行类型转换才能匹配的其他add函数版本。

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

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

相关文章

MySQL 复合查询

实际开发中往往数据来自不同的表&#xff0c;所以需要多表查询。本节我们用一个简单的公司管理系统&#xff0c;有三张表EMP,DEPT,SALGRADE 来演示如何进行多表查询。表结构的代码以及插入的数据如下&#xff1a; DROP database IF EXISTS scott; CREATE database IF NOT EXIST…

理解Java集合的基本用法—Collection:List、Set 和 Queue,Map

本博文部分参考 博客 &#xff0c;强烈推荐这篇博客&#xff0c;写得超级全面&#xff01;&#xff01;&#xff01; 图片来源 Java 集合框架 主要包括两种类型的容器&#xff0c;一种是集合&#xff08;Collection&#xff09;&#xff0c;存储一个元素集合&#xff08;单列…

【看海的算法日记✨优选篇✨】第三回:二分之妙,寻径中道

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出&#xff0c;万山无阻 目录 &#x1f4d6;一、算法思想 细节问题 &#x1f4da;左右临界 &#x1f4da;中点选择 &#x1f4da;…

[CTF/网络安全] 攻防世界 upload1 解题详析

[CTF/网络安全] 攻防世界 upload1 解题详析 考察文件上传&#xff0c;具体原理及姿势不再赘述。 姿势 在txt中写入一句话木马<?php eval($_POST[qiu]);?> 回显如下&#xff1a; 查看源代码&#xff1a; Array.prototype.contains function (obj) { var i this.…

网络安全运行与维护 加固练习题

1. 提交用户密码的最小长度要求。 输入代码: cat /etc/pam.d/common-password 提交答案: flag{20} 2.提交iptables配置以允许10.0.0.0/24网段访问22端口的命令。 输入代码: iptables -A INPUT -p tcp -s 10.0.0.0/24 --dport 22 -j ACCEPT 提交答案: flag{iptables -A I…

PID模糊控制算法(附MATLAB仿真程序)

一、基本原理 PID模糊控制算法是一种将传统PID控制与模糊逻辑相结合的控制策略。它利用模糊逻辑处理不确定性和非线性问题的能力&#xff0c;以提高控制系统的性能。以下是PID模糊控制算法的基本原理&#xff1a; 1.1. **误差和误差变化率的计算**&#xff1a; - 首先&…

【leetcode100】螺旋矩阵

1、题目描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 2、初始思路 2.1 思路 定义上下左右…

2024.11.29(单链表)

思维导图 声明文件 #ifndef __LINKLIST_H__ #define __LINKLIST_H__#include <myhead.h>typedef char datatype; //数据元素类型 //定义节点类型 typedef struct Node {union{int len; //头节点数据域datatype data; //普通节点数据域};struct Node *next; //指针域…

第六届金盾信安杯-SSRF

操作内容&#xff1a; 进入环境 可以查询网站信息 查询环境url https://114.55.67.167:52263/flag.php 返回 flag 就在这 https://114.55.67.167:52263/flag.php 把这个转换成短连接&#xff0c;然后再提交 得出 flag

【Linux】进程控制,手搓简洁版shell

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 1、进程创建2、进程终止3、进程等待4、进程程序替换5、手写简洁版shell 1、进程创建 fork函数&#xff1a;从已经存在的进程中创…

逆向攻防世界CTF系列42-reverse_re3

逆向攻防世界CTF系列42-reverse_re3 参考&#xff1a;CTF-reverse-reverse_re3&#xff08;全网最详细wp&#xff0c;超4000字有效解析&#xff09;_ctfreverse题目-CSDN博客 64位无壳 _int64 __fastcall main(__int64 a1, char **a2, char **a3) {int v4; // [rsp4h] [rbp-…

安装 RabbitMQ 服务

安装 RabbitMQ 服务 一. RabbitMQ 需要依赖 Erlang/OTP 环境 (1) 先去 RabbitMQ 官网&#xff0c;查看 RabbitMQ 需要的 Erlang 支持&#xff1a;https://www.rabbitmq.com/ 进入官网&#xff0c;在 Docs -> Install and Upgrade -> Erlang Version Requirements (2) …

ECharts柱状图-交错正负轴标签,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个柱状图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供…

Scala关于成绩的常规操作

score.txt中的数据&#xff1a; 姓名&#xff0c;语文&#xff0c;数学&#xff0c;英语 张伟&#xff0c;87&#xff0c;92&#xff0c;88 李娜&#xff0c;90&#xff0c;85&#xff0c;95 王强&#xff0c;78&#xff0c;90&#xff0c;82 赵敏&#xff0c;92&#xff0c;8…

【机器学习】入门机器学习:从理论到代码实践

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 机器学习&#xff08;Machine Learning&#xff09;是人工智能的一个分支&#xff0c;它通过算法从数据中学习规律&#xff0c;并基于这些规律进行…

Spring Web开发(请求)获取JOSN对象| 获取数据(Header)

大家好&#xff0c;我叫小帅今天我们来继续Spring Boot的内容。 文章目录 1. 获取JSON对象2. 获取URL中参数PathVariable3.上传⽂件RequestPart3. 获取Cookie/Session3.1 获取和设置Cookie3.1.1传统获取Cookie3.1.2简洁获取Cookie 3. 2 获取和存储Session3.2.1获取Session&…

[Deep Learning] 深度学习中常用函数的整理与介绍(pytorch为例)

文章目录 深度学习中常用函数的整理与介绍常见损失函数1. L2_loss | nn.MSELoss()公式表示&#xff1a;特点&#xff1a;应用&#xff1a;缺点&#xff1a;主要参数&#xff1a;示例用法&#xff1a;注意事项&#xff1a; 2. L1 Loss | nn.L1Loss数学定义&#xff1a;特点&…

0017. shell命令--tac

目录 17. shell命令--tac 功能说明 语法格式 选项说明 实践操作 注意事项 17. shell命令--tac 功能说明 Linux 的 tac 命令用于按行反向输出文件内容&#xff0c;与 cat 命令的输出顺序相反。非常有趣&#xff0c;好记。也就是说&#xff0c;当我们使用tac命令查看文件内…

SpringBoot整合Retry详细教程

问题背景 在现代的分布式系统中&#xff0c;服务间的调用往往需要处理各种网络异常、超时等问题。重试机制是一种常见的解决策略&#xff0c;它允许应用程序在网络故障或临时性错误后自动重新尝试失败的操作。Spring Boot 提供了灵活的方式来集成重试机制&#xff0c;这可以通过…

爬取boss直聘上海市人工智能招聘信息+LDA主题建模

爬取boss直聘上海市人工智能招聘信息 import time import tqdm import random import requests import json import pandas as pd import os from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriv…