2017-01-06 2 views
1

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

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

  • FruitMessage: строка, Int

  • CoordinateMessage: поплавок, поплавок, поплавок

и т.д. и т.д.

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

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

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

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

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

  • Редитор dynamic_casts его, пока он неправильный.

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

Мой вопрос в том, что это стоит избыточности?

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

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

Что мне делать?

+1

Я не уверен, что понял вопрос. Я чувствую, что [виртуальные функции] (http://en.cppreference.com/w/cpp/language/virtual) - это то, что вы ищете. –

+2

Я бы рекомендовал шаблон посетителя: https://sourcemaking.com/design_patterns/visitor/cpp/2 –

+0

Упс, отредактированный. Вы хотите создать виртуальную функцию GetType() и переопределить ее в каждом подклассе, чтобы она вернула правильное значение, соответствующее подклассу? – Tudvari

ответ

2

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

0

Я бы порекомендовал использовать оператор 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

Мне нравится этот путь. Кстати, разве это не плохая практика? – Tudvari

+0

@Tudvari Это не более плохая практика, чем 'dynamic_cast'. Почему вы думаете, что это плохая практика? –

+0

Это признак плохого дизайна. (Как я слышал) – Tudvari