簡體   English   中英

C ++通過類模板函數中的指針訪問類方法

[英]C++ access class method by pointer in class-templated function

我有一些帶有updaterendereventHandler方法的不同類的對象,每個類的原型都相同:

class Menu {
...
public:
    Menu ();

    void update (WindowState *winState);
    void render ();
    void eventHandler (SDL_Event *event);
};

class Game {
...
public:
    Game (Config *config);

    void update (WindowState *winState);
    void render ();
    void eventHandler (SDL_Event *event);
};

因此,我想“設置活動對象”並通過指針調用這些方法:

struct {
    void (*update) (WindowState *winState);
    void (*render) ();
    void (*eventHandler) (SDL_Event *event);
} routines;

template<class T>
void switchRoutines (T *obj) {
    routines.update = &(obj->update);
    routines.render = &(obj->render);
    routines.eventHandler = &(obj->eventHandler);
}
...
switchRoutines<Game> (&game);
...
routines.render ();

但是,我得到類型不匹配:

error: cannot convert 'void (Game::*)(WindowState*)' to 'void (*)(WindowState*)' in assignment
    routines.update = &(obj->update);

我讀過指向類成員的指針應該在其類中明確聲明,但是我的目標是編寫一個通用的,獨立於類的例程切換器。

有沒有一種方法可以使用STL或Boost?

您可以使用類型擦除和模板函數來執行此操作,但是還必須保留對要在其上調用成員函數的實例的引用。
這是一個最小的工作示例:

struct SDL_Event;
struct WindowState;

struct Menu {
    void update (WindowState *) {}
    void render () {}
    void eventHandler (SDL_Event *) {}
};

struct Game {
    void update (WindowState *) {}
    void render () {}
    void eventHandler (SDL_Event *) {}
};

template<typename T, void(T::*)(WindowState *)>
void update(void *ptr, WindowState *winState) {
    static_cast<T *>(ptr)->update(winState);
}

template<typename T, void(T::*)()>
void render(void *ptr) {
    static_cast<T *>(ptr)->render();
}

template<typename T, void(T::*)(SDL_Event *)>
void eventHandler(void *ptr, SDL_Event *event) {
    static_cast<T *>(ptr)->eventHandler(event);
}

struct {
    void (*update) (void *, WindowState *);
    void (*render) (void *);
    void (*eventHandler) (void *, SDL_Event *);
    void *instance;
} routines;

template<class T>
void switchRoutines (T *obj) {
    routines.update = &update<T, &T::update>;
    routines.render = &render<T, &T::render>;
    routines.eventHandler = &eventHandler<T, &T::eventHandler>;
    routines.instance = obj;
}

int main() {
    Game game;
    switchRoutines<Game> (&game);
    routines.render (routines.instance);
}

您的期望值確實存在,但事實上,我添加了一個實例void *指針以使其正常工作:

switchRoutines<Game> (&game);
routines.render (routines.instance);

如果可以將其添加到routines對象中,那么這里是適合您的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM