У меня проблема с указателем на вызов функции-члена. Адрес указателя «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).
Я понятия не имею, чтобы решить это. Пожалуйста, помогите мне исправить.
В вашей обновленной форме ваш код совершенно корректен и не имеет никаких проблем. Единственное объяснение неправильного поведения заключается в том, что вы должны использовать компилятор 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
спецификатор формата для.