为什么结果不符合我的期望?

时间:2011-09-26 07:08:56

标签: c++ function-pointers virtual-functions

#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函数。我不知道为什么,请帮助我

4 个答案:

答案 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的地址),因此是“随机数”。