直接获取类中(非static)成员函数地址的方法

来源:互联网 发布:显卡优化怎么设置 编辑:程序博客网 时间:2024/06/17 13:03

类中的静态成员函数,和非类中的普通函数,函数名即为函数地址:

#include<iostream>using namespace std;class A{public:void fun1(){}static void fun2(){}};void fun3(){}int main(){cout << &A::fun1 << '\t' << A::fun2 << '\t' << fun3 << endl; }

输出为:1       010D1226        010D1249

可以看到后面两个是函数地址,而fun1却是1,而且fun1需要取地址符号&,否则编译不通过:

 'A::fun1': function call missing argument list; use '&A::fun1' to create a pointer to member,编译器不认为A::fun1是一个函数(地址),我单步调试到<ostream>中查看源码,但是f11进去1就已经输出了,这个1是怎么输出出来的,有待研究,知道的人望留言告知。

试了一下用

printf("%p\n", &A::fun1);

能输出地址。这里不纠结了。

既然能直接输出地址,那么就能用普通的函数指针操作类中的成员函数:

#include<iostream>#include<sstream>using namespace std;int trans(string str){stringstream os;os << str;os.flags(os.hex);int temp;os >> temp;return temp;}class A{public:void fun1(){ cout << "fun1 call" << endl; }static void fun2(){}};void fun3(){}typedef void(*P)();int main(){char buf[9];sprintf(buf,"%p", &A::fun1);P pr = (P)trans(string(buf, buf + 8));pr();}

另外附上完整的测试代码(包含用类对象来调用普通成员函数的地址):

#include<iostream>#include<sstream>using namespace std;int trans(string str){stringstream os;os << str;os.flags(os.hex);int temp;os >> temp;return temp;}class A{public:void fun(){cout << "A::fun call" << endl;}static void fun2(){cout << "fun2(static) call" << endl;}};void fun1(){cout << "fun1 call" << endl;}typedef void( A::*p_void_class)();//__thiscalltypedef void(*P_void_normal)();//normalint main(){A a;p_void_class p = &A::fun;char temp[9];sprintf(temp,"%p", p);cout << (void*)trans(string(temp, temp + 8)) << endl;P_void_normal adrr = (P_void_normal)trans(string(temp, temp + 8));//将p转化为普通指针cout << adrr << endl;printf("%p\n", p);//调用printf能输出 __thiscall 函数指针P_void_normal p1 = fun1;P_void_normal p2 = A::fun2;adrr();//调用fun(a.*p)();//调用fun,用对象来调用p1();//调用fun1p2();//调用fun2return 0;}
后来我看到一个“奇怪”的现象,new一个对象的指针,将其delete后,该指针任然能访问其成员函数
A* p = new A;delete p;p->fun1();


这是为何?想了一下想明白了,就算执行p=NULL或者delete p;p的类型不会改变,仅仅是把对象的数据成员占据的内存释放了。既然是A*的类型,当然能访问A里面的成员函数,就像下面这样

//int x=rand();char x='a';((A*)x)->fun1();

不管x是什么东西,字符也好,随机整数也好,只要是能转化成指针类型的都能访问fun1();

这也充分说明类中普通成员函数(有虚函数时只是多了个虚表)和类对象是分离的。所有的类对象访问的是同样的成员函数,和类外的普通函数没什么区别。一个类对象的指针访问成员函数时,该指针的值已经没有任何意义,编译器能直接根据类型找到函数的入口地址。至于如何得到类中成员函数的入口地址,前面已经讲过方法,不再赘述。


0 0
原创粉丝点击