Адрес указателя "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\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).

Я понятия не имею, чтобы решить это. Пожалуйста, помогите мне исправить.

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);

Кроме того, не пытайтесь печатать указатели с %d спецификатор формата в printf, Это еще одно неопределенное поведение прямо здесь. Печать указателей это то, что %p спецификатор формата для.

Другие вопросы по тегам