вроде как применяться должно так:
C++ (Qt)
Type *t = polymorphic_downcast<Type>(obj)
Хотя внутренности говорят, что написать можно было и так:
C++ (Qt)
Type *t = static_cast<Type>(obj)
что явно короче.
Тогда в чём выгода?
Из boost:
The C++ built-in static_cast can be used for efficiently downcasting pointers to polymorphic objects, but provides no error detection for the case where the pointer being cast actually points to the wrong derived class. The polymorphic_downcast template retains the efficiency of static_cast for non-debug compilations, but for debug compilations adds safety via an assert() that a dynamic_cast succeeds.
The C++ built-in dynamic_cast can be used for downcasts and crosscasts of pointers to polymorphic objects, but error notification in the form of a returned value of 0 is inconvenient to test, or worse yet, easy to forget to test. The throwing form of dynamic_cast, which works on references, can be used on pointers through the ugly expression &dynamic_cast<T&>(*p), which causes undefined behavior if p is 0. The polymorphic_cast template performs a dynamic_cast on a pointer, and throws an exception if the dynamic_cast returns 0.
polymorphic_downcast example:
#include <boost/cast.hpp>
...
class Fruit { public: virtual ~Fruit(){}; ... };
class Banana : public Fruit { ... };
...
void f( Fruit * fruit ) {
// ... logic which leads us to believe it is a Banana
Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
...
Описанное решение предлагает ту же семантику, но реализовано посредством не C++-шного dynamic_cast<>(), а Qt-шного qobject_cast<>(). Чем в данном случае qobject_cast<>() лучше/хуже dynamic_cast<>() см. Ассистант.
Похоже не я один такой (
http://www.prog.org.ru/index.php?topic=12932.msg83293#msg83293). Правда в текущей версии я слегка модифицировал код:
C++ (Qt)
template<class T> inline T rzobject_cast(QObject *o)
{
#ifdef QT_DEBUG
if (!qobject_cast<T>(o)) {
if (!o) {
qFatal("rzobject_cast failed cause arg=NULL");
} else {
T target_obj;
qFatal("rzobject_cast failed: got object '%s' class '%s' instead of '%s'",
qPrintable(o->objectName()), o->metaObject()->className(),
target_obj->staticMetaObject.className());
}
Q_ASSERT(!"rzobject_cast fail");
}
#endif
return static_cast<T>(o);
}
Твое решение более информативно в плане сообщений; ничего не имею против, но мне достаточно останова по ассерту с последующим восхождением по стеку в отладчике для локализации ошибки. Все равно эти сообщения не для пользователя, а для программиста.
- создаешь временный объект + тип Т должен быть default constructible, что снижает быстродействие и значительно сужает область применения. Вместо target_obj->staticMetaObject.className() пиши QObject::staticMetaObject.className(); target_obj тут не нужен.