解析C++中函数重载的实现原理

来源:互联网 发布:网络电视机 编辑:程序博客网 时间:2024/06/16 18:14

C++中函数重载

一、定义

    当两个及两个以上函数共用一个函数名,但是形参个数或者类型不同,编译器根据实参与形参的类型及个数的最佳匹配,自动确定调用那一个函数,这就是函数的重载。

     换而言之,在同一作用域,一组函数名相同,参数列表不同(个数和类型),返回类型可同,可不同的情况下,编译器根据调用者传入的参数类型和个数可以唯一可以唯一确定调用哪个函数,这也就是函数的重载。C++中才有此特性。

      例如:

voidOverloadFunc(intx,int d){}
   voidOverloadFunc(intx, double d){}

    voidOverloadFunc(doublex, int d){}

这个是参数列表类型不同的例子,个数不同在此不做赘述。

注意以下三点:

1、为什么返回值类型不同不可以构成重载呢?因为有的函数虽然有返回值类型,但不与参数表达式运算,而作一条单独的语句。

2、怎样会引起二义性?因为函数的重载与带默认值(缺省)的函数一起使用时有可能引起二义性:

例如:                     

void circle(int r=0,int x=0,int y=0);void circle(int r);
当进行调用时,编译系统无法确定调用哪一个函数。

3、在函数调用时,如果给出的实参类型和形参类型不相符,C++编译器会自动做出类型转换工作。若转换成功,则会产生不可识别的错误。

例如:

void fa(int x);void fa(long x);
虽然这两个函数满足重载条件,但如果用下面代码去调用,就会出现上述错误。

                            int c=fa(5.56);

这是因为编译器无法确定将5.56转化成int还是long类型。

二、重载的底层原理


  其实C++函数重载底层实现原理是C++利用name mangling(倾轧)技术,来改名函数名,区分参数不同的同名函数。

   C++中,这三个函数如果在主函数中被调用选择哪一个,由编译器自身决定。那么不同编译器底下函数的命名风格又是怎样的呢?请接着往下看微笑微笑微笑

      再例如:

#include<iostream>using namespace std;int Add(int a, int b){return a + b;}double Add(double a, double b){ return a + b;}int main(){int m = 10;        int n = 20;double a=16.3;double b=15.3;   cout << Add(m,n) << endl;system("pause");return 0;} 


这段代码两个函数Add参数的类型不同,在windows环境下和Linux环境下编译器编译完成后的函数名的命名风格也就不同。以下是在VS2013编译器下编译完成map文件中的函数名,可以看出Addd命名发生改变,一般是 ?[函数名]@@YAHHH@z (只用函数名和YA后面的格式和@z是固定的,剩下的都是固不定的,它的命名代了返回值的参数类型。(H—int,N—double,X—void) 。



同样在linux环境下,这段代码中函数的命名也发生改变,一般是_Z[函数名长度][函数名][参数列表的类型首字母]。



 总的来说:源文件通过编译后,将相同函数名,按照一定的格式,改变成可以区分的,去除了函数在调用时的二义性,从而实现函数的重载。 


 
原创粉丝点击