• 函数重载——C++


    引子:

    国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”
    一样的文字,不同的意思。

    函数重载的定义:

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

    //参数类型不同
    int Add(int a, int b)//Add(2,5)
    {
    	return a + b;
    }
    
    double Add(double a, double b)//Add(2.5,5.5)
    {
    	return a + b;
    }
    
    //类型顺序不同
    double Add(int a, double b)//Add(2,5.5)
    {
    	return (double)a + b;
    }
    
    int Add(double a, int b)//Add(2.5,5)
    {
    	return (int)a + b;
    }
    
    //参数个数不同
    int Add(int a)//Add(5)
    {
    	return a;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    C++支持函数重载的原理——名字修饰

    运行程序的时候,会先进行预处理,编译,汇编,链接
    在链接期间,会将编译期间的符号表合并,里面每个位置都有对应的名和地址,需要调用哪一个内容就根据名字找到符号表中名字对应的地址

    C对于函数的函数名和地址处理到符号表中时,函数名原封不动,所以当有多个同名函数时,编译器无法区分

    但是对于C++来说,在对函数的函数名和地址处理到符号表中时,会根据函数的参数来对函数名进行修饰,


    以下用linux环境下来解释

    1. 采用C语言编译器编译后结果
      在这里插入图片描述
      结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变

    2. 采用C++编译器编译后结果
      在这里插入图片描述
      结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中

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

    函数名修饰在vs下的规则:

    C++编译时函数名修饰约定规则:

    __stdcall调用约定:

    1. 以“?”标识函数名的开始,后跟函数名;

    2. 函数名后面以“@@YG”标识参数表的开始,后跟参数表;

    3. 参数表以代号表示:
        X–void ,
        D–char,
        E–unsigned char,
        F–short,
        H–int,
        I–unsigned int,
        J–long,
        K–unsigned long,
        M–float,
        N–double,
        _N–bool,
        …
        PA–表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复;

    4. 参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前

    5. 参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。其格式为“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,
      例如
      int Test1(char *var1,unsigned long)-----“?Test1@@YGHPAK@Z
      void Test2() -----“?Test2@@YGXXZ


    __cdecl调用约定:

    规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YA”。


    __fastcall调用约定:

    规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YI”。

    VC++对函数的缺省声明是"__cedcl",将只能被C/C++调用

    注意:

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

    int Add(int a, int b)
    {
    	return a + b;
    }
    
    double Add(int a, int b)
    {
    	return a + b;
    }
    
    int main()
    {
    	Add(1,2);
    	Add(2,3);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    其实我们并没有办法区分,编译器也没有办法区分,虽然同名函数返回类型不相同,但是使用这个函数时并不会像定义函数那样标明返回类型,所以我们和编译器都无法区分这个情况

  • 相关阅读:
    详细介绍设计模式七大原则
    PMI-ACP练习题(23)
    基于go-micro微服务的实战-Gateway网关层的限流降级(八)
    .NET 6 实现滑动验证码(二)、基本数据
    本机使用python操作hdfs搭建及常见问题
    Python基本数据类型简介(二)——数值运算操作符与数值运算函数
    RocksDB基本架构与原理详解
    阿里云Redis
    d3ctf_2019_unprintablev **
    【VScode】好用插件集合
  • 原文地址:https://blog.csdn.net/iqrmshrt/article/details/126886142