【问题标题】:C++ access class method by pointer in class-templated functionC++通过类模板函数中的指针访问类方法
【发布时间】:2017-10-08 05:11:22
【问题描述】:

我有一些不同类的对象,它们具有 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?

【问题讨论】:

  • 继承和虚方法?
  • 或者如果类不适合继承结构,模板
  • 不幸的是,您拒绝使用标准库。使用 std::function 而不是原始函数指针会很容易。
  • 在我之后重复(多次):指向非成员函数的指针与指向成员函数的指针相同。最大的区别是成员函数需要调用对象,而非成员函数则不需要。
  • 标准库可以帮助你。不要忽略它!

标签: c++ class templates methods function-pointers


【解决方案1】:

您可以使用类型擦除和模板函数来做到这一点,但您必须还保留对要调用成员函数的实例的引用。
这是一个最小的工作示例:

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 对象中,那么这就是适合您的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 2020-04-24
    • 2015-02-09
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多