Чтобы исправить ваш код:
struct CompareTypeInfo
: std::binary_function<const std::type_info*, const std::type_info*, bool>
{
bool operator()(const std::type_info* a, const std::type_info* b) {
return a->before(*b);
}
};
class Messageable
{
protected:
typedef void (*handlefn)(Messageable *, Message &);
void bindFunction(const std::type_info& type, handlefn func) {
m_handlers[&type] = func;
}
void dispatchMessage(Message& message) {
m_handlers[&typeid(message)](this, message);
}
template <typename S, typename T>
static void handle(Messageable *self, Message &m) {
static_cast<S*>(self)->handleMessage(static_cast<T&>(m));
}
private:
std::map<const std::type_info*, handlefn, CompareTypeInfo> m_handlers;
};
class TestMessageable : public Messageable
{
public:
TestMessageable()
{
this->bindFunction(
typeid(VisualMessage), &Messageable::handle<TestMessageable,VisualMessage>);
this->bindFunction(
typeid(DanceMessage), &Messageable::handle<TestMessageable,DanceMessage>);
}
public:
void handleMessage(VisualMessage visualMessage)
{
//Do something here with visualMessage
}
void handleMessage(DanceMessage danceMessage)
{
//Do something here with danceMessage
}
}
};
Эти статические трансляции могут быть динамическими трансляциями для «дополнительной безопасности» (при условии, что существуют виртуальные функции). Но дизайн означает, что вы знаете, что self должно быть указателем на S, потому что иначе у него не было бы зарегистрировано этой функции, и вы знаете, что m должно ссылаться на T, потому что его typeid уже был проверен в dispatchMessage. Поэтому неудачное приведение не может произойти, если класс используется правильно, и все, что вы можете сделать, если это произойдет, это отладка.
На самом деле, я думаю, что вы могли бы немного сократить словоблудие, сделав шаблон bindFunction также:
template <typename S, typename T>
void bindFunction(void)
{
m_handlers[&typeid(T)] = handle<S,T>;
}
Затем назовите его с:
this->bindFunction<TestMessageable,VisualMessage>();
Но, тем не менее, вы можете понять, почему код двойной отправки Стива Роу обычно предпочтительнее ...