Я пишу некоторый код обработки сообщений, в соответствии с которым каждое сообщение является структурой POD. По способу написания это будет определять абстрактный базовый класс с виртуальной функцией для каждого типа сообщения, например:
class AbstractHandler
{
public:
virtual void handleMessage( const MessageType1& msg ) =0;
virtual void handleMessage( const MessageType2& msg ) =0;
virtual void handleMessage( const MessageType3& msg ) =0;
virtual void handleMessage( const MessageType4& msg ) =0;
};
А затем создайте производные конкретные классы, которые реализуют функции-обработчики:
class ConcreteHandler : public AbstractHandler
{
public:
virtual void handleMessage( const MessageType1& msg );
virtual void handleMessage( const MessageType2& msg );
virtual void handleMessage( const MessageType3& msg );
virtual void handleMessage( const MessageType4& msg );
};
Если новые сообщения добавляются в систему AbstractHandler
должен быть обновлен вместе со всеми производными типами.
В качестве альтернативы я мог бы хранить все поддерживаемые типы сообщений в mpl
последовательность и использование mpl::inherit_linearly
генерировать абстрактный базовый класс.
(Примечание: я уже использую mpl::vector
типов сообщений в другом месте кода. )
например:
typedef mpl::vector< MessageType1, MessageType2,
MessageType3, MessageType4 > message_types;
template< class Message >
class Wrapper
{
public:
virtual void handleMessage( const Message& msg ) = 0;
protected:
~Wrapper(){}
};
class AbstractHandler
: public mpl::inherit_linearly< message_types
, mpl::inherit< mpl_1, Wrapper< mpl::_2 > >
>::type
{
public:
virtual ~AbstractHandler() {}
};
Конкретные обработчики тогда происходят из AbstractHandler
, Это означает, что всякий раз, когда новые типы сообщений добавляются в систему, это просто случай изменения mpl::vector< types... > message_types
последовательность, добавить добавление нового handleMessage
функции для производных классов.
По моему мнению, это сокращает долгосрочное обслуживание, так как AbstractHandler автоматически будет иметь чисто виртуальные функции для всех сообщений в mpl::vector message_types
С точки зрения производительности, есть ли недостатки в использовании этого подхода?
Каковы последствия использования mpl::inherit_linearly
генерировать абстрактные базовые классы?
Я сделал подобный код раньше (и я делаю это снова сегодня).
Там нет никаких затрат, кроме наследственных затрат. Главным образом потому, что окончательный тип определяется во время компиляции, а не во время выполнения.
Однако это, очевидно, может увеличить время компиляции по сравнению с размером списка типов сообщений.
Если, как и я, вы также пишете класс диспетчера сообщений (который может отсылать что угодно к любому обработчику для этого типа), то это может быть дорого во время компиляции.
В противном случае это хорошо.
Просто поймите значение этого вида настройки: список обрабатываемых сообщений определяется во время компиляции, а не во время выполнения. Некоторые системы событий являются средой выполнения из-за требований к использованию. Поэтому убедитесь, что это то, что вы хотите в ваших случаях использования.
Других решений пока нет …