1

メンバー関数呼び出しへのポインターに問題があります。関数ポインター呼び出しの外側のポインター「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) に変更を加えました。

これを解決する手がかりがありません。修正を手伝ってください。

4

1 に答える 1

1

更新されたフォームでは、コードは完全に正しく、何の問題もありません。誤った動作の唯一の説明は、"制限された" メンバー ポインター モデルで MSVC++ コンパイラを使用している必要があることです (これは一般的に正しく動作しません)。実際、メンバー ポインターを変換しようとすると、MSVC++ コンパイラが対応する警告を発行すると思います。警告を無視しただけですか?

とにかく追加

#pragma pointers_to_members( full_generality, virtual_inheritance )

C++ 標準で必要なメンバー関数ポインターの完全な機能を有効にするためにコードに追加すると、コードは正常に動作するはずです。あなたの場合、これ

#pragma pointers_to_members( full_generality, multiple_inheritance )

でも十分なはずです。group のコンパイラ オプションを/vmm, /vms, /vmvと組み合わせて/vmg使用​​すると、同じ効果が得られます。

また、そのようなコンテキストでは C スタイルのキャストを避けてください。使用している変換は、によって実行されますstatic_cast

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

%dまた、フォーマット指定子を使用してポインタを出力しようとしないでくださいprintf。これは、別の未定義の動作です。ポインターの出力は、%pフォーマット指定子の目的です。

于 2014-08-09T17:35:27.403 に答える