【问题标题】:Address of pointer "this" changed unexpectedly inside a pointer to member function call指针“this”的地址在指向成员函数调用的指针内意外更改
【发布时间】:2014-08-09 17:28:54
【问题描述】:

我对指向成员函数调用的指针有疑问。函数指针调用外部的指针“this”的地址与调用内部不同,因此所有对类变量的访问都会导致错误的值。

我在这里包含代码。

class ClassInterface
{
public:
    ClassInterface(void);
    ~ClassInterface(void);
};

class ClassA:public ClassInterface
{
public:
    float   _a;
public:
    ClassA(void);
    ~ClassA(void);

    virtual void Update();
};


class ClassB:public ClassA
{
public:
    ClassB(void);
    ~ClassB(void);

    void Update();

    void ProcessTaskB(void*);
};

//ClassB.CPP
void ClassB::ProcessTaskB(void*)
{
    printf("ClassB::ProcessTaskB\n");

    printf("Address of myB INSIDE callback = %d\n",this);
    _a += 100;
}

//test CPP
#include "stdafx.h"
#include "ClassInterface.h"
#include "ClassA.h"
#include "ClassB.h"

typedef void (ClassInterface::*Callback) (void* );

int _tmain(int argc, _TCHAR* argv[])
{
    ClassA* myA = new ClassA();
    ClassB* myB = new ClassB();

    Callback fptrB = (Callback) &(ClassB::ProcessTaskB);

    printf("Address of myB outside callback = %d\n",myB);

    (myB->*fptrB)(NULL);

    return 0;


}

这是输出:

Address of myB OUTSIDE callback = 1332696
Address of myB INSIDE callback = 1332700

因此语句 _a += 100;不改变_a。它更改了地址 (&_a + 4)。

我不知道如何解决这个问题。请帮我解决。

【问题讨论】:

  • 什么ClassAClassInterface 与任何类有什么关系?
  • _a的声明在哪里?是成员变量吗?静态还是非静态?
  • 我刚刚编辑了我的代码。这就是所有的代码。 ClassInterface 与任何其他类无关,_a 是 ClassA 的成员变量

标签: c++ member-function-pointers this-pointer


【解决方案1】:

在您更新后的表格中,您的代码完全正确,没有任何问题。对错误行为的唯一解释是您必须在某些“受限”成员指针模型中使用 MSVC++ 编译器(在一般情况下工作不正确)。事实上,我相信当您尝试转换成员指针时,MSVC++ 编译器会发出相应的警告。您是否忽略了警告?

不管怎样,添加

#pragma pointers_to_members( full_generality, virtual_inheritance )

您的代码是为了启用 C++ 标准所需的成员函数指针的全部功能,并且您的代码应该可以正常工作。在你的情况下这个

#pragma pointers_to_members( full_generality, multiple_inheritance )

应该足够了。来自/vmm, /vms, /vmv 组的编译器选项与/vmg 组合可达到相同的效果。

另外,避免在这种情况下使用 C 风格的强制转换。您正在使用的转换是由static_cast执行的

Callback fptrB = static_cast<Callback>(&ClassB::ProcessTaskB);

另外,不要尝试在printf 中打印带有%d 格式说明符的指针。这是另一个未定义的行为。打印指针是 %p 格式说明符的用途。

【讨论】:

  • 我不一定将 不同broken this 指针等同起来。在我们未显示的代码部分中可能存在多重继承。
  • 说,问题不是表明ClassInterface 没有V-Table 而ClassB 有吗? (虽然在 OP 提供的代码中并不明显)。
  • @barak manos:问题是由ClassA 中引入的vtable 指针触发的。但是,C++ 标准要求此代码正常工作。为了使其正常工作,OP 必须将他的编译器从“简化”成员指针支持模式切换到“完全标准”成员指针支持模式。一切都会按预期开始。
  • @AndeyT:我尝试了您的解决方案,但没有成功。地址还是不一样。
  • @user2512031:解决方案是正确的,而且效果很好。您一定是把#pragma 放在了错误的地方。它必须位于最顶部,并且必须在每个文件中都可见。无论如何,忘记 pragma 并更好地更改全局项目设置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-26
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多