传递 Inherited Class 的成员函子
Passing Inherited Class's Member Functor
我正在使用 C++ 编写游戏代码。我想将 Child
的成员函数绑定到委托中。
我想像这样使用简化代码的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
class中实现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
变成模板。生成的代码几乎总是一样的。唯一的区别可能在于实际演员表的执行方式。
所以你会得到相当多的代码膨胀,这都是因为一个非常小的差异。我建议您封装这种差异。为此,将辅助类型添加到 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++ 编写游戏代码。我想将 Child
的成员函数绑定到委托中。
我想像这样使用简化代码的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
class中实现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
变成模板。生成的代码几乎总是一样的。唯一的区别可能在于实际演员表的执行方式。
所以你会得到相当多的代码膨胀,这都是因为一个非常小的差异。我建议您封装这种差异。为此,将辅助类型添加到 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
。