C++从入门到精通——函数重载

函数重载

  • 前言
  • 一、函数重载概念
  • 二、函数重载的分类
    • 参数类型不同的函数重载
    • 参数个数不同的函数重载
    • 参数类型顺序不同的函数重载
  • 三、函数重载的具体代码展示
    • main.cpp
  • 四、为什么为什么C++支持函数重载,而C语言不支持函数重载呢


前言

函数重载是指在同一个作用域内,可以定义多个名称相同但参数列表不同的函数。这些函数具有不同的参数个数、类型或顺序,以便编译器能够根据传入的参数来确定调用哪个函数。函数重载使得代码更加简洁,避免了命名上的冗余,并提高了代码的可读性和可维护性。通过重载,我们可以为不同的操作或数据类型提供统一的接口,使得函数的使用更加灵活和方便。


一、函数重载概念

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或类型或类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

函数重载概念是编程中的一个重要特性,它允许在同一作用域内定义多个同名函数,但这些函数的参数列表(参数的数量、类型或顺序)必须不同。通过这种方式,函数重载为程序员提供了更大的灵活性,使得他们可以根据不同的参数类型和数量来调用不同的函数实现,从而实现功能的多样化和代码的复用。

在C++、Java等面向对象的编程语言中,函数重载是一种常见且有用的编程技巧。通过使用函数重载,开发者可以为类或者命名空间中定义的行为提供多个入口,以适应不同的数据类型或调用场景。例如,一个名为add的函数可以被重载以处理整数加法、浮点数加法和复数加法等不同类型的数据。

重载函数时,编译器会根据函数调用时传递的参数类型和数量来决定调用哪一个版本的函数。这要求重载的函数在参数特征上必须有所区别,否则会导致编译错误。这种机制使得代码更加清晰易读,同时也提高了代码的复用性和可维护性。

需要注意的是,虽然函数重载提供了很大的便利,但过度使用也可能导致代码难以理解和维护。因此,在设计和实现函数重载时,开发者需要权衡其带来的好处和可能带来的问题,确保代码的可读性和可维护性。

总之,函数重载概念是编程中一种重要的技术,它允许我们根据参数的不同来调用不同的函数实现,从而提高了代码的复用性和灵活性。正确合理地使用函数重载,可以帮助我们编写出更加高效、易读和可维护的代码。

二、函数重载的分类

C++函数重载可以分为以下几种分类:

  • 参数个数不同:在同一个作用域中,函数名相同但参数个数不同的多个函数被视为重载函数。

  • 参数类型不同:在同一个作用域中,函数名相同但参数类型不同的多个函数被视为重载函数。

  • 参数顺序不同:在同一个作用域中,函数名相同但参数顺序不同的多个函数被视为重载函数。

需要注意的是,返回值类型不是函数重载的条件,因为编译器无法通过返回值类型来确定调用哪个重载函数。此外,函数重载必须在同一个作用域内进行,否则编译器无法识别不同作用域中的重载函数。

参数类型不同的函数重载

// 参数类型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}
double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
}

在这里插入图片描述

参数个数不同的函数重载

//参数个数不同
void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "f(int a)" << endl;
}

在这里插入图片描述

参数类型顺序不同的函数重载

//参数类型顺序不同
void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}

在这里插入图片描述
注意:像这种有歧义的输入编译器是会报错的,因为编译器不知道你是想要字符型还是ASCII码
在这里插入图片描述

三、函数重载的具体代码展示

main.cpp

#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}
double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
}
// 2、参数个数不同
void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}
int main()
{Add(10, 20);Add(10.1, 20.2);f();f(10);f(10, 'a');f('a', 10);//f('a', 'a');return 0;
}

在这里插入图片描述

四、为什么为什么C++支持函数重载,而C语言不支持函数重载呢

C++支持函数重载,而C语言不支持函数重载的原因是因为它们在语言设计上有不同的目标和考虑。

C语言是一种相对简单的编程语言,它的设计目标是提供一种简洁、高效的工具来进行系统级编程。因此,C语言主要关注的是语言的简洁性和效率,而不是提供过多的语言特性。所以C语言中的函数只能有一个名称,没有函数重载的概念。

相比之下,C++是一种更为复杂和功能更强大的编程语言。它在C语言的基础上添加了许多面向对象的特性,并且支持更高级的编程抽象。其中一个特性就是函数重载。函数重载允许在同一个作用域内定义多个同名函数,但它们的参数类型或数量不同。这样可以方便地编写功能类似但输入输出不同的函数,提高了程序的灵活性和可读性。

除语言设计上有不同的目标和考虑之外,C++支持函数重载的原理是因为C++存在名字修饰(name Mangling)

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。

我们以c语言为例,关于具体的编译和链接的过程可看——C语言从入门到实战——编译和链接

在这里插入图片描述
在这里插入图片描述

  1. 实际项目通常是由多个头文件和多个源文件构成,而通过C语言从入门到实战——编译和链接这篇文章,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么怎么办呢?
  2. 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。在这里插入图片描述

ps:出现上述情况的原因就是因为编译器在链接的过程中没有找到函数的地址,我们可以检查是不是自己的函数写错了

  1. 那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。

  2. 由于Windowsvs的修饰规则过于复杂,而Linuxg++的修饰规则简单易懂,下面我们使用了g++演示了这个修饰后的名字。

  3. 通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】

    • 采用C语言编译器编译后结果
      在这里插入图片描述

    • 结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。

    • 采用C++编译器编译后结果
      在这里插入图片描述

    • 结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。

    • Windows下名字修饰规则
      在这里插入图片描述
      对比Linux会发现,windowsvs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了。

    • 【扩展学习:C/C++ 函数调用约定–里面有对vs下函数名修饰规则讲解】

  4. 通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

  5. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。


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

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

相关文章

SpringMVC注解及使用规则

文章目录 前言一、SpringMVC注解是什么&#xff1f;二、使用步骤1.注解使用2创建JSP3 SpringMVC视图1. 逻辑视图&#xff08;Logical View&#xff09;2. 物理视图&#xff08;Physical View&#xff09;区别和关系 4 SpringMVC注解总结 总结 前言 提示&#xff1a;这里可以添…

Python批量提取图像灰度共生矩阵(GLCM)、支持批量处理、任意图像格式

目录 一、介绍 二、实现 1、特征计算 2、批量处理 3、结果 一、介绍 灰度共生矩阵(Grey Level Co-occurrence Matrix)也叫做空间灰度级依赖矩阵(SGLDM),它是一种基于统计的纹理特征提取的方法。 一般包括四个方向&#xff1a; (a,b)(1,0)&#xff0c;像素对是水平的&am…

千川素材投放效果如何追踪:精准识别爆款、潜力、首发、优质素材

在数字营销和广告领域&#xff0c;素材投放的效果直接关乎广告的成功与否。为了在竞争激烈的市场中脱颖而出&#xff0c;广告主和广告从业者需要密切关注素材投放效果&#xff0c;并及时识别出不同类型的素材&#xff0c;如爆款、潜力、首发和优质素材。本文将详细探讨如何进行…

淘宝订单中的涉及红包检测、优惠券检测方案|工具|API

首先&#xff0c;检测订单红包的核心价值是什么&#xff1f; “红包的本质就是薅平台羊毛&#xff1a;不用怀疑&#xff0c;平台对于这种损害平台利益的行为肯定是最高等级的稽查”。那么&#xff0c;在日常运营中&#xff0c;需要尽可能过滤这类订单。 其次&#xff0c;如何使…

一站式学习:iOS手机抓包工具使用指南及实例分享

&#x1f4f1; 最近又发现APP Store一款宝藏软件&#xff0c;克魔助手抓包工具&#xff0c;app刚上架&#xff0c;功能不断迭代中&#xff0c;目前18软妹币实惠价可享受终身版&#xff01;现在是下手的最好时机。 引言 移动端开发中&#xff0c;抓包工具已成为必备的工具之一…

设计模式——结构型——外观模式Facade

处理器类 public class Cpu {public void start() {System.out.println("处理器启动了...");} } 内存类 public class Memory {public void start() {System.out.println("内存启动了...");} } 硬盘类 public class Disk {public void start() {Syste…

C++:sizeof关键字(7)

sizeof用于统计数据所占用内存的大小 用法&#xff1a;sizeof( 变量名称 / 变量) 直接上代码&#xff0c;可以在让大家直观的感受到sizeof关键字的用法 #include<iostream> using namespace std;// 语法&#xff1a; sizeof&#xff08;数据类型|变量名&#xff09;// 用…

“直播曝光“有哪些媒体直播分流资源?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 我们线下举办活动时&#xff0c;往往希望活动进行更大的曝光&#xff0c;随着视频直播越来越被大众认可&#xff0c;甚至成了活动的标配&#xff0c;那么做活动视频直播的时候&#xff0…

C# 操作 Word 全域查找且替换(含图片对象)

目录 关于全域查找且替换 Word应用样本 SqlServer数据表部分设计样本 范例运行环境 配置Office DCOM 设计实现 组件库引入 实现原理 查找且替换的核心代码 窗格内容 页眉内容 页脚内容 形状内容 小结 关于全域查找且替换 C#全域操作 Word 查找且替换主要包括如下…

java 抠取红色印章(透明背景)

一个亲戚让我帮他把照片里的红色印章抠出来&#xff0c;&#xff0c;&#xff0c;记录下处理过程&#xff0c;代码如下&#xff0c;可直接用&#xff1a; public static void signatureProcess(String sourceImagePath, String targetImagePath) {Graphics2D graphics2D null…

鸿蒙原生应用开发-网络管理HTTP数据请求

一、场景介绍 应用通过HTTP发起一个数据请求&#xff0c;支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。 二、接口说明 HTTP数据请求功能主要由http模块提供。 使用该功能需要申请ohos.permission.INTERNET权限。 涉及的接口如下表&#xff0c;具体的…

小白了解Pinia第2集 · 三大核心状态Getters、Actions以及Plugins 插件

三大核心状态 state 第1集有详细讲解&#xff1a;https://blog.csdn.net/qq_51463650/article/details/137137080?spm1001.2014.3001.5501 getters Getter 完全等同于 Store 状态的 计算值。 它们可以用 defineStore() 中的 getters 属性定义。 他们接收“状态”作为第一个…