#include <iostream>
using namespace std;
typedef void (*pFun)(void);
class A
{
private:
int a;
int b;
virtual void outPrint()
{
cout << b << endl;
}
public:
A()
{
a = 3;
b = 4;
}
};
int main()
{
A obj;
cout << *((int*)(&obj)+1) << endl;
pFun pFunc;
pFunc = (pFun)*((int*)*(int*)(&obj));
pFunc();
system("pause");
return 0;
}
当我调用pFunc()时,我认为结果应该是4,但实际上它是一个随机数。 我调试程序,发现pFunc指向outPrint函数。我不知道为什么,请帮助我
答案 0 :(得分:2)
似乎您假设对象obj
的地址可以解释为您定义的类型函数的地址。
它不能。
我不完全确定你为什么要开始这样的假设。您可能正在考虑动态调度的内部实现。但请注意:您期望被调用的A::outPrint
,接受1个参数(this
,未明确定义),而您的typedef不承担任何参数。因此,即使地址转换工作正常并且您获得的地址是成员函数的地址(这是一个开头的延伸),您的调用也是错误的。
如果您将typedef更改为:
typedef void (*pFun)(A*);
并致电
pFunc(&obj);
这可能有用。然而,根据我的理解,每个规范的行为是不确定的。
答案 1 :(得分:1)
在遍历int*
时,仅向int[]
添加1已定义行为。
在其他所有情况下,都没有定义应该发生什么。它是实现定义的,因为未定义成员的最终内存位置。
尝试以不利用编译器细节但标准的方式解决问题。
此外,如果您按照这种方式获得函数地址,将其作为静态方法(没有对象)调用,只会给您带来几个麻烦。
答案 2 :(得分:0)
我不太确定你究竟想要做什么。看起来你正试图直接操作指针以获取方法的地址,但这对于大约6种不同的原因来说是一个非常糟糕的主意。可以获取指向类方法的指针,但它没有绑定到对象,所以你需要小心。
我建议您对指针和C ++类有一个基本的误解,必须先纠正它,然后才能安全地管理它们。大多数人不需要函数指针,几乎没有人需要方法指针。
答案 3 :(得分:0)
您依赖于各种“未定义的行为”,因此结果取决于您运行的编译器和平台。
(int *)&amp; obj + 1(如果你写((int *)&amp; obj)+1,以避免误解),不一定是b
成员。成员之间可能存在填充,并且&amp; obj可能与&(obj.a)
是obj一个多态对象不同(因此可能在它顶部有一个vtable指针)。
如果是这种情况,*(int*)&obj
是被视为int的vtable地址。将其转换为int*
(假设int和指针具有相同的大小),它指向第一个vtable条目(很可能是outPrint的地址),因此是“随机数”。