本文介绍了指针的地址“this”在指向成员函数调用的指针内意外更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题的指针成员函数调用。在函数指针调用之外的指针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\\\
);

printf(myB INSIDE callback的地址=%d \\\
,this);
_a + = 100;
}

//测试CPP
#includestdafx.h
#includeClassInterface.h
#includeClassA.h
#includeClassB.h

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

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

回调fptrB =(回调)&(ClassB :: ProcessTaskB);

printf(myB outside callback =%d\\\
的地址,myB);

(myB-> * fptrB)(NULL);

return 0;


}

p>

  myB OUTSIDE回调的地址= 1332696 
myB INSIDE回调的地址= 1332700

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



我没有办法解决这个问题。请帮助我修复。

解决方案

在更新的表单中,代码是完全正确的,没有任何问题。对不正确行为的唯一解释是,你必须在一些限制成员指针模型(在一般情况下不正确工作)中使用MSVC ++编译器。事实上,我相信MSVC ++编译器在尝试转换成员指针时会发出相应的警告。



无论如何,添加

  pragma pointers_to_members(full_generality,virtual_inheritance)

为了启用成员函数指针的完整功能通过C ++标准,你的代码应该工作得很好。

  #pragma pointers_to_members(full_generality,multiple_inheritance)

应该足够了。与 / vmm,/ vms,/ vmv 组合的编译器选项与 / vmg 组合实现相同的效果。 p>

此外,在这种上下文中避免使用C风格的转换。正在使用的转换由 static_cast

 执行回调fptrB = static_cast< ; Callback>(& ClassB :: ProcessTaskB); 

此外,请勿尝试使用%d 格式说明符在 printf 中。这是另一个未定义的行为。打印指针是%p 的格式说明符。


I have problem with the pointer to member function call. The address of pointer "this" outside the function pointer call is different than inside the call thus all access to the class variables results wrong values.

I include the code here.

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;


}

And this is the output:

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

Thus the statement _a += 100; does not make change to _a. It made change to address (&_a + 4).

I have no clue to resolve this. Please help me fix.

解决方案

In your updated form your code is perfectly correct and has no problems whatsoever. The only explanation for the incorrect behavior is that you must be using MSVC++ compiler in some "restricted" member pointer model (which works incorrectly in general case). In fact, I believe MSVC++ compiler issues the corresponding warnings when you attempt to convert your member pointers. Did you just ignore the warning?

Anyway, add

#pragma pointers_to_members( full_generality, virtual_inheritance )

to you code in order to enable full functionality of member function pointers required by C++ standard, and your code should work fine. In your case this

#pragma pointers_to_members( full_generality, multiple_inheritance )

should be sufficient though. Compiler options from /vmm, /vms, /vmv group in combination with /vmg achieve the same effect.

Also, avoid C-style casts in such contexts. The conversion you are using is performed by static_cast

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

Also, don't attempt to print pointers with %d format specifier in printf. This is another undefined behavior right there. Printing pointers is what %p format specifier is for.

这篇关于指针的地址“this”在指向成员函数调用的指针内意外更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 10:14