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

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

#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)();//__thiscall
typedef void(*P_void_normal)();//normal
int 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();//调用fun1
	p2();//调用fun2
	return 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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值