C++学习之函数重载内幕

众所周知,重载(overload)是C++区别C的重要特征之一。所谓重载就是指在同一个作用域中,函数名相同,参数表不同的函数。(注意:对于不在同一作用域中的,要遵循标识符隐藏的原则)

举例说明:

  1 #include
  2 using namespace std;
  3 
  4 void func(int a,char c)
  5 {
  6     cout << "func(1)" << endl;
  7 }
  8 
  9 void func(int a, char * p)
 10 {
 11     cout << "func(2)" << endl;
 12 }
 13 
 14 int main(void)
 15 {
 16     int a =10;
 17     char c = 'a';
 18     func(a,c);
 19     func(a,&c);
 20     return 0;
 21 }
当然,上面这个例子很简单,我们很容易判断出调用的函数是哪一个。但是,有些时候函数调用时传递的实参并不是和形参标准的对应,这时候编译器就会按照某些原则进行判断。比如:

 14 void foo(char *p , int c){cout << "foo(1)" << endl;}
 15 void foo(const char *p , char c){cout << "foo(2)" << endl;}
 16 
 17 int main(void)
 18 {
 19     int a =10;
 20     char c = 'a';
 21 //  func(a,c);
 22 //  func(a,&c);
 23     foo(&c,c);
 24     return 0;
 25 }
结果: foo(2)

个人认为原因有:1.更安全 2.相比foo(1)减少了工作量.

那么重载在C++中到底时如何实现的呢? 是通过更换函数名来实现的。我们假设第一个例子编译之后得到的是a.out(g++编译器),我们用命令 nm a.out 来看一些编译之后的结果:

root@wang-Inspiron-1525:/home/wang/cpp# nm a.out 
08049f10 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
08048755 t _GLOBAL__sub_I__Z4funcic
0804884c R _IO_stdin_used
         w _Jv_RegisterClasses
080486ae T _Z3fooPKcc
08048682 T _Z3fooPci
08048715 t _Z41__static_initialization_and_destruction_0ii
08048656 T _Z4funciPc
08048624 T _Z4funcic
         U _ZNSolsEPFRSoS_E@@GLIBCXX_3.4
         U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
         U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
0804a040 B _ZSt4cout@@GLIBCXX_3.4
         U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4
0804a0d4 b _ZStL8__ioinit
         U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4
08049f00 d __CTOR_END__
08049efc d __CTOR_LIST__
08049f08 D __DTOR_END__
08049f04 d __DTOR_LIST__
08048a38 r __FRAME_END__
08049f0c d __JCR_END__
08049f0c d __JCR_LIST__
0804a028 A __bss_start
         U __cxa_atexit@@GLIBC_2.1.3
0804a020 D __data_start
08048800 t __do_global_ctors_aux
080485a0 t __do_global_dtors_aux
0804a024 D __dso_handle
         w __gmon_start__
08049efc t __init_array_end
08049ef8 t __init_array_start
080487f0 T __libc_csu_fini
08048780 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
08048590 T __x86.get_pc_thunk.bx
0804a028 A _edata
0804a0d8 A _end
0804882c T _fini
08048848 R _fp_hw
080484a0 T _init
08048560 T _start
0804a0cc b completed.6159
0804a020 W data_start
0804a0d0 b dtor_idx.6161
08048600 t frame_dummy
080486e0 T main
这样一坨......呵呵,我们找找有没有眼熟的东东。最后一行是main......好吧,好眼力。还有呢?
080486ae T _Z3fooPKcc
08048682 T _Z3fooPci
这个不是foo函数么?怎么成这个鬼样子?这就时编译之后的模样了。对于_Z3fooPKcc来说,3是指函数原名的字符个数,P是指指针,K是指const,c是指char ,另一个c还是char。最前面的一串十六进制应该就是地址了。新的函数名中包含了形参的信息,这样同一名字,不同的形参表的函数就得以区分了呀。

那么C语言编译之后的结果是什么样子的呢?为什么C不支持重载呢?

我们用C编译器看一下 , main.c

  1 #include
  2 
  3 int main()
  4 {
  5     printf("%d\n",add(100,200));
  6     return 0;
  7 }
gcc -c main.c  

nm main.o

         U add
00000000 T main
         U printf
果然,add函数名并没有被改变。





你可能感兴趣的:(C++,函数,重载)