В моем проекте у меня есть дерево QObjects с различными типами. Позвольте мне привести простой пример, который должен дать вам представление о том, о чем я говорю. Это может быть примерное дерево QObject (не диаграмма наследования, но несколько похожая на диаграмму классов), где мы начинаем с корневого объекта вверху и перечисляем его дочерние объекты ниже:
City
|
Street
/ \
House ...
/ \
Floor ...
/ \
Room ...
Хотя дерево QObject не обязательно следует этому правилу, в моем случае у самого класса в дереве есть родительский элемент один конкретный тип. Таким образом, для примера, в доме может быть несколько этажей и детей других типов, но этаж — это ребенок дома и только дом.
Теперь, если я моделирую их как производные классы QObject, интерфейс class Floor
должен дать мне его House *house()
внутренне глядя, что QObject::parent()
является. Я действительно знаю, что этот родитель будет иметь тип House*
потому что я разработал это так, и программисты (ы) придерживаются этого дизайна.
Это нормально, если я в стиле C произнесу QObject *parent()
в House*
реализовать House *house() const
?
Qt предлагает использовать qobject_cast<House*>(parent())
, возвращаясь 0
если QObject* parent()
не наследуется от House
, делая литой тип безопасным. Но в режиме релиза я хочу избежать таких медленных бросков. Я профилировал один конкретный алгоритм, который работает в три раза быстрее при выполнении приведения в стиле C вместо qobject_casts. Это связано с тем, что qobject_cast запрашивает мета-объект о типе-info во время выполнения, что приводит к значительному замедлению при вызове. очень довольно часто.
Итак, что я закончил, было:
House *Floor::house() const {
Q_ASSERT(qobject_cast<House*>(parent()));
return (House*)parent();
}
Это будет утверждать в режиме отладки, что родитель действительно является Домом, в то время как эффективное приведение стиля C в режиме выпуска.
Чтобы прийти к сути: Я знаю, что люди будут кричать, когда программисты C ++ будут делать приведения в стиле C, но будет ли это нормально в этой ситуации?
Альтернативным решением было бы дополнительно хранить родительские указатели определенных типов в качестве переменных-членов, но я думаю, что это избыточно, и мне также нравится, что дерево отражается в тех методах, которые возвращают родительские элементы дерева.
Если вы уверены, что график владения не изменится даже во время обслуживания, тогда приведение, которое не проверено на тип, является безопасным. Ты можешь использовать static_cast<House*>(parent())
, что быстро, или, если вы действительно хотите, бросок в стиле C — это нормально. Но приведение в стиле C не быстрее, чем C ++ static_cast
,
Других решений пока нет …