динамическая трансляция или избыточность?

В моей системе низкоуровневые объекты взаимодействуют с высокоуровневым объектом посредством вызова функции высокоуровневого объекта +1 уровня, которая вызывает функцию высокоуровневого объекта +1 уровня и т. Д. И т. Д., Пока вызов функции не остановится у получателя.

Существует абстрактный класс Message, и есть много производных классов, которые содержат различные типы данных.
Подобно:

  • FruitMessage: строка, int

  • CoordinateMessage: плавать, плавать, плавать

и т. д.

И те методы, о которых я упоминал ранее, нуждаются в объектах Message, так что это согласование выполняется с помощью одного вида методов вместо создания методов для всех типов сообщений.

Проблема возникает, когда получатель получает объект сообщения.

Получатель хочет знать что в этом сообщении, так может процесс получает сообщение, как того требует тип сообщения.

(как это уменьшает целое число на 1 в FruitMessages, делит координаты в CoordinateMessages и т. д.)

В настоящее время у меня есть две идеи, но, возможно, ни одна из них не верна, и я должен использовать третью. (скажи мне, пожалуйста)

  • Получатель dynamic_casts это пока он не имеет правильный тип.

  • Сообщение имеет поле перечисления с именем MessageType, которое инициализируется в конструкторе производного класса до правильного значения, поэтому получатель просто использует регистр переключения во время процесса.

У меня вопрос, стоит ли резервирование?

  • dynamic_cast медленнее, чем целочисленная проверка

  • но каждый раз, когда я создаю новый класс Message, мне нужно создавать новое значение перечисления.

Что я должен делать?

1

Решение

Оба способа в порядке. Избыточность в зависимости от скорости является очень распространенной проблемой при разработке программного обеспечения.
Я бы выбрал dynamic_cast, так как избыточность — это первый шаг к ошибкам, но это действительно зависит от вас и зависит от ваших требований к производительности.
Я видел очень похожую проблему при работе с Akka, они обычно используют dynamic_cast (я имею в виду аналоги java / scala)

2

Другие решения

Я бы порекомендовал использовать typeid Оператор, чтобы проверить тип сообщения. Таким образом, вы избегаете повторного вызова dynamic_cast пока вы не получите правильный тип.

void process_message(Message const& msg) {
if (typeid(msg) == typeid(FruitMessage)) {
auto& fruit_msg = static_cast<FruitMessage const&>(msg);
…
}
}

Еще лучше, вы могли бы использовать C ++ 17 std::any Тип контейнера. any Объект может быть скопирован как неполиморфное значение, и не требует использования виртуального базового класса. Если у вас нет доступа к реализации библиотеки C ++ 17, вы можете использовать boost::any вместо.

void process_message(std::any const& msg) {
if (msg.type() == typeid(FruitMessage)) {
auto fruit_msg = std::any_cast<FruitMessage>(msg);
…
}
}

Что касается использования enum поле будет быстрее, чем typeid или же any, вам придется сделать бенчмаркинг самостоятельно.

0

По вопросам рекламы [email protected]