设为首页 加入收藏

TOP

如何实现C的函数重载(二)
2013-07-22 17:56:40 来源: 作者: 【 】 浏览:359
Tags:如何 实现 函数 重载

 

  .cfi_startproc

  pushl %ebp

  .cfi_def_cfa_offset8

  .cfi_offset5, -8

  movl %esp, %ebp

  .cfi_def_cfa_register5

  andl $-16, %esp

  subl $16, %esp

  call_Z4funcv

  movl $5, (%esp)

  call_Z4funci

  movl $0x40a00000, %eax

  movl %eax,4(%esp)

  movl $5, (%esp)

  call_Z4funcif

  movl $0, %eax

  leave

  .cfi_restore5

  .cfi_def_cfa4,4

  ret

  .cfi_endproc

  可以看到,func 的三个版本重载函数在编译后名字都被破坏了,编译器将他们重命名为了 _Z4funcv, _Z4funci, _Z4funcif, (g++ 编译器可能根据函数参数类型为函数名加上了与参数类型相关的特定后缀,如func(void) 变成了 _Z4funcv,  func(int) 变成了_Z4funci , func(int, float)变成了 _Z4funcif ),然后在调用各个版本的func()时,编译器根据参数类型的不同选择合适的重载函数,如调用 func() 其实是调用了 _Z4funcv, 调用 func(5, 5.0)实际上是调用了 _Z4funcif等。

  但是,在很多情况下,利用可变参数可以实现 C 语言的函数重载的,POSIX 接口中定义的 open 函数就是一个非常好的例子,

  #include <sys/types.h>

  #include<sys/stat.h>

  #include<fcntl.h>

  intopen(constchar*pathname,intflags);

  intopen(constchar*pathname,intflags, mode_t mode);

  第二个 open 函数的第三个参数用来表明创建文件的权限,所以这就是 C 实现函数重载活生生的例子 :-)

  那么如何实现 C 的函数重载呢,比较通用的做法是利用 C 的可变参数va_args:

  #include <stdarg.h>

  voidva_start(va_list ap, last);

  type va_arg(va_list ap, type);

  voidva_end(va_list ap);

  voidva_copy(va_list dest, va_list src);

  以下是一个简单的例子,"重载"了两个函数,第一个函数是两个参数,第二个函数带了三个函数,其中第三个函数是可选的,

  #include <stdio.h>

  #include<stdarg.h>

  voidva_overload2(intp1,intp2)

  {

  printf("va_overload2 %d %d\n", p1, p2);

  }

  voidva_overload3(intp1,intp2,intp3)

  {

  printf("va_overload3 %d %d %d\n", p1, p2, p3);

  }

  staticvoidva_overload(intp1,intp2, ...)

  {

  if(p2 ==3)

  {

  va_list v;

  va_start(v, p2);

  intp3 = va_arg(v,int);

  va_end(v);

  va_overload3(p1, p2, p3);

  return;

  }

  va_overload2(p1, p2);

  }

  那么调用的时候可以如下调用:

  #include <stdio.h>

  intmain()

  {

  va_overload(1,2);

  va_overload(1,2,3);

  return0;

  }

  除了根据参数个数实现重载以外,还可以实现参数类型的重载(typeof),这主要是利用了 GCC 的内置函数,__builtin_types_compatible_p()和__builtin_choose_expr(),

  例如:

  structs1

  {

  inta;

  intb;

  doublec;

  };

  structs2

  {

  longlonga;

  longlongb;

  };

  voidgcc_overload_s1(structs1 s)

  {

  printf("Got a struct s1: %d %d %f\n", s.a, s.b, s.c);

  }

  voidgcc_overload_s2(structs2 s)

  {

  printf("Got a struct s2: %lld %lld\n", s.a, s.b);

  }

  //warning: dereferencing type-punned pointer will break strict-aliasing rules

  #definegcc_overload(A)\

  __builtin_choose_expr(__builtin_types_compatible_p(typeof(A),structs1),\

  gcc_overload_s1(*(structs1 *)&A),\

  __builtin_choose_expr(__builtin_types_compatible_p(typeof(A),structs2),\

  gcc_overload_s2(*(structs2 *)&A),(void)0))

        

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言实现简单的倒排文件索引 下一篇设置缓存失效的三种方式

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: