12

私が持っているとしましょう:

void Render(void(*Call)())
{
    D3dDevice->BeginScene();
    Call();
    D3dDevice->EndScene();
    D3dDevice->Present(0,0,0,0);
}

staticレンダリングに使用する関数が関数またはメンバー関数である限り、これは問題ありません。

Render(MainMenuRender);
Render(MainMenu::Render);

ただし、ほとんどの場合、レンダリング関数はメンバー変数にアクセスする必要があり、クラス インスタンスをグローバルにしない方がよいため、クラス メソッドも使用できるようにしたいと考えています。

Render(MainMenu->Render);

ただし、これを行う方法がまったくわかりませんが、関数とstaticメンバー関数を使用できるようにしています。

4

6 に答える 6

14

テンプレートを含め、この猫の皮を剥ぐ方法はたくさんあります。私のお気に入りはBoost.functionです。長期的に見て最も柔軟であることがわかったからです。また、Boost.bindを参照して、メンバー関数へのバインドやその他の多くのトリックを確認してください。

次のようになります。

#include <boost/bind.hpp>
#include <boost/function.hpp>

void Render(boost::function0<void> Call)
{
    // as before...
}

Render(boost::bind(&MainMenu::Render, myMainMenuInstance));
于 2008-09-13T13:02:16.110 に答える
3

void Wrap(T *t)呼び出すだけのラッパー関数を作成し、そのt->Call()ようRenderな関数をオブジェクトと一緒に取得できます。あれは:

void Wrap(T *t)
{
  t->Call();
}

void Render(void (*f)(T *), T *t)
{
  ...
  f(t);
  ...
}
于 2008-09-13T13:01:57.560 に答える
2

C++ FAQ: メンバーへのポインターについてはどうですか?

于 2008-09-13T13:55:09.803 に答える
1

インスタンスへのポインターをメンバーとして受け入れるグローバル関数「Call」を定義することで、一度そうしました

void CallRender(myclass *Instance)
{
  Instance->Render();
}

したがって、render は次のようになります。

void Render(void (*Call)(myclass*), myclass* Instance)
{
  ...
  Call(Instance);
  ...
}

render の呼び出しは次のとおりです。

Render(CallRender, &MainMenu);

私はそれが醜いことを知っていますが、私にとってはうまくいきました(pthreadsを使用していました)

于 2008-09-13T13:04:02.923 に答える
1

オブジェクトへの参照も持っていない限り、ポインターからメンバー関数を呼び出すことはできません。例えば:

((object).*(ptrToMember))

したがって、render メソッドのシグネチャを変更せずにこれを実現することはできません。 この記事では、これが一般的に悪い考えである理由を説明します。

より良い方法は、render メソッドを持つクラスが実装できる "Renderer" インターフェイスを定義し、それをメインの Render メソッドのパラメーター型にすることです。次に、「StaticCaller」実装を記述して、参照による静的メソッドの呼び出しをサポートできます。

例(私のC ++は本当に錆びています。これもコンパイルしていません)。



void Render(IRenderer *Renderer)
{
    D3dDevice->BeginScene();
    Renderer->Render();
    D3dDevice->EndScene();
    D3dDevice->Present(0,0,0,0);
}

// The "interface"
public class IRenderer 
{
public:
    virtual void Render();
};

public class StaticCaller: public IRenderer
{
    void (*Call)();
public:

    StaticCaller((*Call)())
    {
        this->Call = Call;
    }

    void Render()
    {
        Call();
    }
};

これはすべて定型文ですが、読みやすくする必要があります。

于 2008-09-13T13:19:34.493 に答える
0

以下を使用して、クラス T のメンバー関数への関数ポインターを宣言できます。

typedef void (T::*FUNCTIONPOINTERTYPE)(args..)
FUNCTIONPOINTERTYPE function;

そして、次のように呼び出します。

T* t;
FUNCTIONPOINTERTYPE function;
(t->*function)(args..);

これを、変数の引数、型、戻り値などを使用して有用なカリー化システムに外挿するのは、単調で面倒です。前述のブースト ライブラリについて良いことを聞いたことがあります。

于 2008-12-09T22:40:35.310 に答える