【C++】函数重载详解

这篇具有很好参考价值的文章主要介绍了【C++】函数重载详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C语言下的函数名弊端

#include <stdio.h>

int Add(int a, int b)
{
    return a + b;
}

我编写了一个简单的 Add 函数来执行整数相加,它既简单又能够达到我想要的效果。然而,如果我现在需要一个能够执行浮点数相加的函数怎么办呢?一种方法是重新编写一个函数,但是问题是该如何命名呢?已经有一个 Add 函数了,如果取相同的名字就会出现命名冲突,而重新选择名字又显得繁琐。为了解决这个问题,C++中引入了函数重载。

概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或类型或类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
注意:对返回值没有要求。如果返回值不同也能构成重载的话,那么当调用两个无参且返回值不同的同名函数时,到底是调用哪一个函数编译器并不清楚,会产生二义性。

参数类型不同

#include <iostream>
using namespace std;

int Add(int x, int y)
{
    return x + y;
}

double Add(double x, double y)
{
    return x + y;
}

int main()
{
    printf("%d\n", Add(1, 2));
    printf("%lf\n", Add(3.2, 2.8));

    return 0;
}

这里两个同名函数参数类型不同构成重载。

值得注意的是:在调用存在函数重载的函数时,传入的参数类型要与期望调用的函数的参数类型匹配,否则可能会导致歧义。例如,下面的代码中,调用 Add 函数时,传入的参数 3.2 和 1 的类型分别为 double 和 int,可能导致编译器无法确定应该调用哪个重载函数。在这个示例中,我们只需要屏蔽掉两个 Add 函数中的一个就不会报错了(会发生隐式类型转化)。

【C++】函数重载详解,c++,开发语言 

参数个数不同

#include <iostream>
using namespace std;

void funcA()
{
    cout << "funcA()" << endl;
}

void funcA(int a)
{
    cout << a << endl;
}

int main()
{
    funcA();
    funcA(1);

    return 0;
}

参数个数不同同样构成重载。 

我在上一篇博客中介绍了缺省参数:给传参加上自动挡-CSDN博客 
可能你会好奇,如果上面第二个 funA 函数的形参加上缺省值能不能构成重载呢?我们来试下吧。

【C++】函数重载详解,c++,开发语言

我们看到编译器直接红温了。因为当调用无参的 funcA 函数时编译器不知道调用的是哪个函数,可能你是真的无参,可能你是想用缺省值,这就造成了二义性。所以如果你写了这样的两个函数,当你调用时必须要传参。这里也可以发现这两个函数确实构成了重载,它们的参数个数确实是不同的。但是也只能调用带参数的那个函数,所以看似写了两个函数,实际上只有一个是可以用的。因此这种重载的形式是没意义的

参数类型顺序不同

#include <iostream>
using namespace std;

void fun(char a, int b)
{
    cout << "fun(char a, int b)" << endl;
}

void fun(int a, char b)
{
    cout << "fun(int a, char b)" << endl;
}

int main()
{
    fun('a', 1);
    fun(1, 'a');

    return 0;
}

这里虽然两个函数的参数类型都是一个 int 一个 char,但是顺序不同,因此也构成重载。

为什么支持函数重载

到目前为止,你应该对C++中函数重载的条件和价值有了初步的了解。那么,为何C语言不支持这样的高级功能,而C++却能够做到呢?下面我们将更深入地探讨这个问题。

回顾一下,在C/C++中,程序的运行经历了四个关键步骤

1. 预处理阶段:在这个阶段,主要完成宏替换、头文件展开、注释删除以及条件编译等操作。处理后会生成一个后缀为 .i 的文件,为后续编译过程提供了基础。

2. 编译:.i 文件的基础上进行语法检查,包括语法分析、词法分析、语义分析和符号汇总等操作。这个阶段的输出是一个汇编代码文件(.s 文件)。值得强调的是,在生成汇编代码时,函数的调用会被标记为一个 call 指令,其中存储了该函数在代码段的地址。当程序执行到这个 call 指令时,会跳转到相应的函数汇编代码处,并开始创建函数栈帧以及执行具体函数的实现。需要特别注意的是,如果函数的定义和声明分离,这里的 call 指令并没有具体的地址,只是先标记个名字,具体的函数地址会在最后的链接阶段通过这个名字去查找。如果找不到函数定义,链接阶段会报错。

3. 汇编:将代码翻译成机器语言,简单来说就是将 .s 文件中的汇编代码转换成二进制的机器码并生成 .o 文件。并且会生成符号表,符号表记录了程序中使用的各种符号(如变量、函数名、常量等)以及它们在内存中的地址或其他相关信息

4. 链接:将编译生成的目标文件合并为可执行文件。在链接阶段,编译器将解析符号引用,确定符号的地址,执行重定位,最终生成一个包含所有必要信息的可执行文件,以便在运行时被操作系统加载和执行。这一过程确保了程序的各个部分正确连接,并能够在内存中协同工作。编译中提到的链接不确定的函数地址就是在这一步骤中通过合并汇总后的符号表完成的。链接成功后,windows下生成后缀为 .exe的可执行文件,Linux下则是默认生成 a.out 的可执行文件。

现在你对这四个步骤已经有一定的了解了,那么我们来解决如何寻找函数地址,也就是如何为函数命名的问题。这里以Linux下的 gcc 和 g++编译器来展示C和C++在编译阶段是怎么为函数命名的。

首先来看 C++对应的 g++编译器是怎么做的: 

【C++】函数重载详解,c++,开发语言

这里我用 vim 写了一段代码,接下来我们看一下用 g++编译过后的结果:

【C++】函数重载详解,c++,开发语言

可以发现在Linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。修饰过后的名字以 _Z 开头,接着是函数名的字符个数,然后是函数名,最后是参数类型的简称。这也就解释了为什么函数重载支持参数个数、类型、类型顺序的不同,但不支持返回值的不同,因为在这个命名规则中并未包含返回值信息

接下来用同一段代码我们来看看C语言编译器也就是Linux下的gcc编译器是怎么命名的:

【C++】函数重载详解,c++,开发语言

注意到了吧,在Linux下使用gcc编译后,函数名并没有被修饰,仍然保持原始函数名。这也解释了为什么C语言无法支持函数重载,因为同名函数将无法被编译器区分

windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,这里就不做细致的研究了,感兴趣的话可以上网找一下相关资料。文章来源地址https://www.toymoban.com/news/detail-772865.html

到了这里,关于【C++】函数重载详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ 学习 ::【基础篇:05】:C++ 函数重载认识及使用、简单介绍:C++ 支持函数重载的原因

    本系列 C++ 相关文章 仅为笔者学习笔记记录,用自己的理解记录学习!C++ 学习系列将分为三个阶段: 基础篇、STL 篇、高阶数据结构与算法篇 ,相关重点内容如下: 基础篇 : 类与对象 (涉及C++的三大特性等); STL 篇 : 学习使用 C++ 提供的 STL 相关库 ; 高阶数据结构与算

    2024年02月06日
    浏览(52)
  • 【C++】函数重载 & 引用 & 内联函数

    目录 一,函数重载 1,函数重载的概念 2,C++支持函数重载的原理 二,引用 1,引用概念 2,引用特性 3,常引用 4,做参数 5,做返回值 6,传值、传引用效率比较 7,值和引用的作为返回值类型的性能比较 8,引用和指针的区别 三,内联函数 1,概念 2,特性 自然语言中,一个

    2024年02月08日
    浏览(40)
  • c++ ——命名空间、缺省函数、函数重载

    在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存 在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化, 以避免命名冲突或名字污染,namespace的出现就是针对这种问题的 简单一句话命

    2024年02月16日
    浏览(49)
  • C++ 面向对象(3)——重载运算符和重载函数

    C++ 允许在同一作用域中的某个 函数 和 运算符 指定多个定义,分别称为 函数重载 和 运算符重载 。 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。 当您调用一个 重载函数 或 重载运算符 时

    2024年02月10日
    浏览(53)
  • C++入门:函数缺省参数与函数重载

    目录 1.函数缺省参数 1.1 缺省参数概念 1.2 缺省参数分类 2.函数重载 2.1 函数重载概念 2.2 C++支持函数重载的原理 缺省参数是 声明或定义函数时 为函数的 参数指定一个缺省值 。在调用该函数时,如果没有指定实 参则采用该形参的缺省值,否则使用指定的实参,有点备胎的意

    2024年02月12日
    浏览(32)
  • 【C++入门】函数重载

    函数重载就是在同一个作用域内,允许存在参数不同的同名函数 。 例子: 例子: 例子: 注意这里的顺序指的是参数类型的顺序,而不是参数名的顺序。 比如下面的例子就不构成函数重载。 C++ 支持函数重载的本质,其实是因为 C++ 特殊的函数名修饰规则。 我们知道 C 语言

    2024年02月15日
    浏览(33)
  • C++系列-函数重载

    函数名可以相同, 提高复用性 同一个作用域下 函数名相同 函数参数不同 – 参数个数不同 – 参数顺序不同 – 参数类型不同 不可以使用返回值作为重载的条件 引用作为重载 参数可以分为const和非const。 函数重载遇到默认参数

    2024年02月12日
    浏览(35)
  • 【C++】函数重载及引用

    目录 一、函数重载  1、函数重载的概念  2、名字修饰 二、引用  1、引用概念  2、引用特性  3、常引用  4、引用的使用场景    4.1 做参数    4.2 做返回值  5、传值、传引用效率比较  6、引用和指针的区别 函数重载: 是函数的一种特殊情况,C++允许在 同一作用域中 声明

    2024年02月10日
    浏览(37)
  • 函数重载和引用【C++】

    函数重载: 重载函数是函数的一种特殊情况。 为方便使用,C++允许在 同一作用域 中声明几个功能类似的 同名 函数,但是这些同名函数的形式参数(指1.参数的个数 2.类型 3.顺序)必须 至少有一个 不同 根据这些同名函数的参数表的不同, 达成传入参数类型不同,调用的函

    2024年04月08日
    浏览(54)
  • C++语言基础——函数(详解)

    目录 函数是什么 函数的定义 主函数举例  空函数 函数的调用 语法格式 举例说明:计算x的n次方 递归 递归的主要点 递归的结构 条件 递归使用的场景 函数全名叫 计算机函数 ,它可以帮助你完成一些特定的程序。你可以把它简单理解成一把手枪。 手枪的作用: 完成几发子

    2024年01月21日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包