我正在使用 C++ 编写游戏代码。我想将 Child
的成员函数绑定(bind)到委托(delegate)中。
我想使用 init_and_bind
函数,如下简化代码:
class Parent {
protected:
Widget* widget;
};
class Child : public Parent {
public:
void foo() {
widget->init_and_bind(this, &Child::bar);
}
void bar() { /* do something */ }
};
我想在Widget
类中实现init_and_bind
,所以我实现了如下代码:
// pre-defined in engine
void Delegate::bind(Parent* object, void(Parent::* function)());
void Widget::init_and_bind(Parent* object, void(Parent::* function)()) {
init();
delegate->bind(object, function);
}
但是这不起作用。因为init_and_bind
的第二个参数只接受Parent的成员仿函数类型。所以我无法传递 Child 的成员仿函数。所以我尝试使用模板和reinterpret_cast
:
template<typename T>
void Widget::init_and_bind(Parent* object, void(T::* function)()) {
init();
delegate->bind(object, function); // error
delegate->bind(object, reinterpret_cast<void(Parent::*)()>(function); // error
}
但它也不起作用。因为它无法将 Child
的仿函数转换为 Parent
的仿函数。
那么,init_and_bind
的第二个参数应该是什么类型?
最佳答案
虽然直接的解决方案是static_cast
,但我认为您不应该将init_and_bind
变成模板。生成的代码总是几乎相同。唯一的区别可能在于实际 Actor 阵容的执行方式。
所以你会得到相当多的代码膨胀,这都是因为一个非常小的差异。我建议您将这种差异封装起来。为此,向 Widget
添加一个辅助类型:
class Widget {
struct MemFunc {
void(Parent::* function)();
template<class T>
MemFunc(void(T::* func)()) :
function(static_cast<void(Parent::*)()>(func))
{}
};
void init_and_bind(Parent* object, MemFunc mf) {
init();
delegate->bind(object, mf.function);
}
};
这样,实际上只有需要模板化的一小段代码才被模板化。最好的是,它在调用方上透明地发生。它甚至可能不会引起任何肿胀。因为您的原始非模板版本无论如何都要求调用者static_cast
。
关于c++ - 传递继承类的成员仿函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46925511/