注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

太阳神上的博客

青青子衿,悠悠我心,但为君故,沉吟至今。

 
 
 

日志

 
 
 
 

获取C++类的成员函数指针  

2007-08-19 05:57:12|  分类: 学习 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

  在C++里,类的函数分为成员函数和静态函数两种,而实际上静态函数和C语言的全局函数一样,因此其名称就可以得到相应的入口地址,可以传递作为一种函数指针而操作,直接用&Classname::StaticMethodName就可以取址了,调用时也是与C语言的函数完全一样的使用,那成员函数,则可以使用C++的“指向类成员的指针”可实现,可参考:http://blog.csdn.net/xmouse/archive/2005/12/23/560080.aspx
  但是使用指向类成员的指针,我觉得使用起来总觉得不如静态的那样灵便。其实在C++编译器实现时,类的成员函数和静态函数也是一样的普通函数,只不过多了一个this指针的参数,由于是类的重载等原因,其链接名通过了name mangling,是一个非常奇怪丑陋的名字(当然只要是C++函数,链接名都很丑陋)。可以通过g++的-S选项生成汇编代码,再查看这个汇编代码就可以得知其真实的链接名,由于C语言的函数名与链接名保持一致,于是可以通过extern "C"的声明直接引用这个函数。举个例子:

 #include <stdio.h>

class Person{
private:
    int id;
public:
    Person(int id):id(id){
    }
   
    int getID(){
        return id;
    }
};

int main(){ 
    Person p(5);
    printf("%d\n",p.getID());
    return 0;
}

通过-S选项生成的汇编代码如下:

  .file "test.cpp"
 .def ___main; .scl 2; .type 32; .endef
 .section .rdata,"dr"
LC0:
 .ascii "%d\12\0"
 .text
 .align 2
.globl _main
 .def _main; .scl 2; .type 32; .endef
_main:
 pushl %ebp
 movl %esp, %ebp
 subl $24, %esp
 andl $-16, %esp
 movl $0, %eax
 addl $15, %eax
 addl $15, %eax
 shrl $4, %eax
 sall $4, %eax
 movl %eax, -8(%ebp)
 movl -8(%ebp), %eax
 call __alloca
 call ___main
 movl $5, 4(%esp)
 leal -4(%ebp), %eax
 movl %eax, (%esp)
 call __ZN6PersonC1Ei
 leal -4(%ebp), %eax
 movl %eax, (%esp)
 call __ZN6Person5getIDEv
 movl %eax, 4(%esp)
 movl $LC0, (%esp)
 call _printf
 movl $0, %eax
 leave
 ret
 .section .text$_ZN6Person5getIDEv,"x"
 .linkonce discard
 .align 2
.globl __ZN6Person5getIDEv
 .def __ZN6Person5getIDEv; .scl 2; .type 32; .endef
__ZN6Person5getIDEv:
 pushl %ebp
 movl %esp, %ebp
 movl 8(%ebp), %eax
 movl (%eax), %eax
 popl %ebp
 ret
 .section .text$_ZN6PersonC1Ei,"x"
 .linkonce discard
 .align 2
.globl __ZN6PersonC1Ei
 .def __ZN6PersonC1Ei; .scl 2; .type 32; .endef
__ZN6PersonC1Ei:
 pushl %ebp
 movl %esp, %ebp
 movl 8(%ebp), %edx
 movl 12(%ebp), %eax
 movl %eax, (%edx)
 popl %ebp
 ret
 .def _printf; .scl 2; .type 32; .endef

 可以找到Person类的getID函数的链接名叫__ZN6Person5getIDEv,于是在源文件中加入:

 extern "C" {
    int _ZN6Person5getIDEv(Person *);
}

#define Person__getID _ZN6Person5getIDE

使用时就用Person__getID(&p)就可以了。把它看成一个第一个参数是Person*类型的全局函数就可以了。
这个方法可以使得不支持类的C语言也可以正常调用C++的类的成员函数了。C++可以向下兼容C,C语言也可以通过这个方法“偷偷”调用C++的函数了。

  评论这张
 
阅读(1716)| 评论(3)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017