QT API里关于qobject_cast的描述:

T qobject_cast ( QObject * object )

Returns the given object cast to type T if the object is of type T (or of a subclass); otherwise returns 0. If object is 0 then it will also return 0.

The class T must inherit (directly or indirectly) QObject and be declared with the Q_OBJECT macro.

A class is considered to inherit itself.

Example:


 QObject *obj = new QTimer;          // QTimer inherits QObject

 QTimer *timer = qobject_cast<QTimer *>(obj);
 // timer == (QObject *)obj

 QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
 // button == 0

 

The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries.

Warning: If T isn't declared with the Q_OBJECT macro, this function's return value is undefined.

大体意思就鼓励大家使用qobject_cast而非dynamic_cast。xxx_cast<TA>(TB),转换是否成功主要看TA/TB是否在一个类继承体系中,TB是否是TA相同类型或者子类。dynamic_cast依赖RTTI类判断,而qobject_cast依赖QMetaObject信息来判断。下面来看看源代码吧:

// */src/corelib/kernel/qmetaobject.cpp

 

 
  
  1. template <class T>  
  2. inline T qobject_cast(QObject *object)  
  3. {  
  4. #if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)  
  5.  
  6.     reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object));  
  7.  
  8.     //首先检查是类T定义中是否使用了宏Q_OBJECT。如果使用了,那么qt_check_for_QOBJECT_macro就有了定义, 
  9.  
  10.     //但是操作实际上是没有任何意义;如果没用到这个宏,那么就出现编译错误,因为Q_OBJECT的展开中 
  11.  
  12.     //才有这个函数的定义 
  13.  
  14. #endif  
  15.     return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object));  
  16.  
  17. //真正检查对象的元信息的代码,具体看下边的QObject::cast(QObject*)。这里staticMetaObject 
  18.  
  19. //是static变量,所以可以用强制转换0地址为对象指针的方法来调用。又是一个0地址的用处哦 
  20.  
  21. }  
  22.  
  23. template <class T>  
  24. inline T qobject_cast(const QObject *object)  
  25. {  
  26.     // this will cause a compilation error if T is not const  
  27.  
  28.     register T ptr = static_cast<T>(object);  
  29.  
  30.     Q_UNUSED(ptr);  
  31.  
  32. #if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)  
  33.  
  34.     reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));  
  35.  
  36. #endif  
  37.  
  38.     return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object))));  
  39. }  

// */src/corelib/kernel/qobjectdefs.h

 
  
  1. /* This is a compile time check that ensures that any class cast with qobject_cast 
  2.    actually contains a Q_OBJECT macro. Note: qobject_cast will fail if a QObject 
  3.    subclass doesn't contain Q_OBJECT. 
  4.  
  5.    In qt_check_for_QOBJECT_macro, we call a dummy templated function with two 
  6.    parameters, the first being "this" and the other the target of the qobject 
  7.    cast. If the types are not identical, we know that a Q_OBJECT macro is missing. 
  8.  
  9.    If you get a compiler error here, make sure that the class you are casting 
  10.    to contains a Q_OBJECT macro. 
  11. */ 
  12.  
  13. /* tmake ignore Q_OBJECT */ 
  14. #define Q_OBJECT_CHECK \ 
  15.     template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const \ 
  16.     { int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; } 
  17.   //这个"i=i;“是多余之笔吗?如果谁看出门道来告诉我,好不好?
  18. //上边注释中第二段说的不是废话吗?能进到这个函数里就说明Q_OBJECT已经有使用了,已经达到目的了
  19. template <typename T> 
  20. inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; } 
  21. //没用啊
  22.  
  23. template <typename T1, typename T2> 
  24. inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {} 

// */src/corelib/kernel/qobjectdefs.h 

 
  
  1. #define Q_OBJECT \ 
  2. public: \ 
  3.     Q_OBJECT_CHECK \  //上边几个函数就此展开
  4.     static const QMetaObject staticMetaObject; \ 
  5.     Q_OBJECT_GETSTATICMETAOBJECT \ 
  6.     virtual const QMetaObject *metaObject() const; \ 
  7.     virtual void *qt_metacast(const char *); \ 
  8.     QT_TR_FUNCTIONS \ 
  9.     virtual int qt_metacall(QMetaObject::Call, intvoid **); \ 
  10. private

// */src/corelib/kernel/qmetaobject.cpp

 
  
  1. /*! 
  2.     \internal 
  3.     Returns \a obj if object \a obj inherits from this 
  4.     meta-object; otherwise returns 0. 
  5. */ 
  6. QObject *QMetaObject::cast(QObject *obj) const 
  7.     if (obj) { 
  8.         const QMetaObject *m = obj->metaObject(); 
  9.         do { 
  10.             if (m == this
  11.                 return const_cast<QObject*>(obj); 
  12.         } while ((m = m->d.superdata));  //通过MetaObject信息比对来决定返回的内容 
  13.     } 
  14.     return 0; //如果在继承体系中没找到相应的metaobject信息,那么返回0 

 最后说一句,上边说qobject_cast可以跨动态库的。网上没找到有人解释这句话,我猜想,可能意思是支持不同动态库的对象的转换,例如QObject和QWidget,隐含的条件当然是“被转换的对象,都从QObject这个根上继承下来的”,这个就好理解了。

以上就是qobject_cast()相关的代码。读一读然后写一些自己的理解和不懂的地方,收获还是很大的。有问题也请指正。