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++ 常见问题解答:指向成员的指针怎么说?

于 2008-09-13T13:55:09.803 回答
1

我这样做了一次,它定义了一个全局函数“Call”,它接受指向您的实例的指针作为成员

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

所以渲染变成:

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

您对渲染的调用是:

Render(CallRender, &MainMenu);

我知道它很难看,但对我有用(我使用的是 pthreads)

于 2008-09-13T13:04:02.923 回答
1

除非您也引用了该对象,否则您不能从指针调用成员函数。例如:

((object).*(ptrToMember))

因此,如果不更改渲染方法的签名,您将无法实现这一目标。 本文解释了为什么这通常是一个坏主意。

更好的方法可能是定义一个“渲染器”接口,您的具有渲染方法的类可以实现该接口,并将其作为您的主要渲染方法的参数类型。然后,您可以编写一个“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..);

将其推断为具有可变参数、类型、返回值等的有用柯里化系统是单调且令人讨厌的。我听说过关于上述 boost 库的好消息,所以我建议在做任何激烈的事情之前先调查一下。

于 2008-12-09T22:40:35.310 回答