[英]C++ access class method by pointer in class-templated function
我有一些带有update
, render
和eventHandler
方法的不同类的对象,每个类的原型都相同:
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.