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

发布于 2024-12-06 08:50:07 字数 584 浏览 0 评论 0原文

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

#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; 
}

when i call pFunc(), the result i think should be 4,but actually it's a random number.
and i debug the program, finding that pFunc points to the outPrint function. i don't know why,plz help me

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白日梦 2024-12-13 08:50:07

似乎您假设对象 obj 的地址可以解释为您定义的类型的函数的地址。

它不能。

我不完全确定你为什么一开始会有这样的假设。您可能正在假设有关动态调度的内部实现的事情。但请注意:您希望调用的 A::outPrint 接受 1 个参数(this,未明确定义),而您的 typedef 假定没有参数。因此,即使地址转换工作正常并且您获得的地址是成员函数的地址(这从一开始就是一个延伸),您的调用也是不正确的。

如果将 typedef 更改为:

typedef void (*pFun)(A*);

并且对 That 的调用

pFunc(&obj);

可能会起作用。然而,据我所知,每个规范的行为是未定义的。

Seems that you assume that the address of the object obj can be interpreted as an address of a function of the type you defined.

It cannot.

I'm not entirely sure why would you have such an assumption to begin with. You're probably assuming things about the internal implementation of the dynamic dispatch. But do take a note: A::outPrint that you expect to be called, accepts 1 parameter (this, that is not explicitly defined), whereas your typedef assumes no parameters. So even if the address casting works fine and the address you get is that of the member function (which is a stretch to begin with), your call is incorrect.

If you change the typedef to:

typedef void (*pFun)(A*);

and the call to

pFunc(&obj);

That might work. Yet, the behavior per spec is undefined, to the best of my understanding.

〆一缕阳光ご 2024-12-13 08:50:07

仅在遍历 int[] 的情况下,向 int* 加 1 才具有定义的行为。

在所有其他情况下,都没有定义应该发生什么。它是实现定义的,因为成员的最终内存位置未定义。

尝试以不利用编译器细节而是利用标准的方式解决问题。

另外,如果您按照这种方式获得函数地址,将其作为静态方法(没有对象)调用,只会给您带来一些麻烦。

Adding 1 to a int* only has defined behaviour in the case of traversing an int[].

Every other cases, there are no definition of what should happen. It is implementation defined since the final memory position of the members are not defined.

Try solving the problem in a way that does not exploit compiler details but the standard.

Also, in the case you get the function address following this way, calling it as a static method (without an object), only can provide you several headaches.

佼人 2024-12-13 08:50:07

我不太确定你到底想做什么。看起来您正在尝试直接操作指针来获取方法的地址,但由于大约 6 个不同的原因,这是一个非常糟糕的主意。可以获取指向类方法的指针,但它并未绑定到对象,因此您需要小心。

我建议您对指针和 C++ 类有一个根本性的误解,必须先纠正这些误解,然后才能安全地管理其中的任何内容。大多数人不需要函数指针,几乎没有人需要方法指针。

I'm not quite sure what exactly it is you're trying to do. It looks like you're trying to directly manipulate the pointer in order to get the address of a method, but that's a very bad idea for about 6 different reasons. It is possible to get a pointer to a class method, but it's not bound to the object so you need to be careful.

I'd suggest you have a fundamental misunderstanding of pointers and C++ classes, which must be corrected before you can manage any of this safely. Most people don't need function pointers, and almost nobody needs method pointers.

冷夜 2024-12-13 08:50:07

您依赖于各种“未定义的行为”,因此结果取决于您运行的编译器和平台。

(int*)&obj+1(最好写为 ((int*)&obj)+1 以避免误解)不一定是 b 成员。成员之间可能存在填充,并且 &obj 可能与 &(obj.a) 不同,obj 是一个多态对象(因此它的顶部可能有一个 vtable 指针) 。

如果是这种情况,*(int*)&obj 就是被视为 int 的 vtable 地址。将其转换为 int* (假设 int 和指针具有相同的大小),它指向第一个 vtable 条目(很可能是 outPrint 的地址),因此是“随机数”。

You are relying on various "undefined behavior", hence the result depends on what compiler and platform you are running on.

(int*)&obj+1 (better if you write ((int*)&obj)+1 to avoid misinterpretations) is not necessarily the b member. There may be padding between members, and &obj may be not the same as &(obj.a) being obj a polymorphic object (so may be it has a vtable pointer in top of it).

If this is the case, *(int*)&obj is the vtable address treated as an int. Converting it to an int* (supposing int and pointer having same sizes) it points to the first vtable entry (most likely the address of outPrint), hence the "random number".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文