Frage

Sagen, ich habe:

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

Das ist in Ordnung, solange die Funktion, die ich verwenden mag eine Funktion oder eine static Memberfunktion zu machen ist:

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

Allerdings möchte ich wirklich in der Lage sein, da die Rendering-Funktion in den meisten Fällen auch eine Klassenmethode verwenden wollen Membervariablen für den Zugriff auf und Id eher nicht die Klasseninstanz global machen, z.

Render(MainMenu->Render);

Allerdings habe ich wirklich keine Ahnung, wie dies zu tun, und immer noch erlauben, Funktionen und static Elementfunktionen verwendet werden.

War es hilfreich?

Lösung

Es gibt viele Möglichkeiten, diese Katze Haut, einschließlich Vorlagen. Mein Favorit ist Boost.Function wie ich habe fand es die flexibelste auf lange Sicht zu sein. Auch lesen Sie auf Boost.Bind für die Bindung an Mitgliederfunktionen sowie viele andere Tricks.

Es würde wie folgt aussehen:

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

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

Render(boost::bind(&MainMenu::Render, myMainMenuInstance));

Andere Tipps

Sie können eine Wrapper-Funktion void Wrap(T *t) machen, die nur t->Call() Anrufe und haben Render zusammen mit einem Objekt eine solche Funktion übernehmen. Das heißt:

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

void Render(void (*f)(T *), T *t)
{
  ...
  f(t);
  ...
}

ich so einmal war durch eine globale Funktion „Call“ definiert, die einen Zeiger auf Ihre intance als Mitglied akzeptiert

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

So machen wird:

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

Und Ihr Anruf zu machen ist:

Render(CallRender, &MainMenu);

Ich weiß, es ist hässlich, aber war für mich (ich war mit pthreads)

Sie können keine Member-Funktion von einem Zeiger aufrufen, wenn Sie auch einen Verweis auf das Objekt haben. Zum Beispiel:

((object).*(ptrToMember))

Sie werden also nicht in der Lage sein, dies zu acheive ohne die Signatur Ihrer Render-Methode zu ändern. Diese Artikel erklärt, warum dies in der Regel eine schlechte Idee .

Eine bessere Möglichkeit könnte sein, einen „Renderer“ Schnittstelle zu definieren, die Ihre Klassen, die Methoden machen haben implementieren können und dass der Parameter Typ Ihres Haupt Render-Methode sein. Sie könnten dann eine „StaticCaller“ Implementierung schreiben die Berufung Ihrer statischen Methoden durch Bezugnahme zu unterstützen.

eg (Mein C ++ wirklich rostig ist, ich habe das nicht entweder kompiliert).



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

Das alles ist ziemlich vorformulierten aber es sollte für mehr Lesbarkeit machen.

Sie können einen Funktionszeiger auf eine Elementfunktion der Klasse T deklarieren mit:

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

Und rufen Sie es wie:

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

diese in nützliche currying System mit variablen Argumenten Rechnet man, Typen, Rückgabewerte, etc., ist eintönig und nervig. Ich habe gute Dinge über die oben genannte Boost-Bibliothek gehört, also würde ich empfehlen, in die Suche vor drastisch etwas zu tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top