Qobject_castはどのように機能しますか?
-
12-10-2019 - |
質問
QTで次のコードを見つけたばかりで、ここで何が起こっているのか少し混乱しています。
特に何について reinterpret_cast<T>(0)
やりますか?
template <class T>
inline T qobject_cast(const QObject *object)
{
// this will cause a compilation error if T is not const
register T ptr = static_cast<T>(object);
Q_UNUSED(ptr);
#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)
reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
#endif
return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object))));
}
誰かが説明したいですか?
解決
これは少し複雑です...
それを覚えておいてください qobject_cast<T>(obj)
動的にキャストする方法です QObject
ターゲットタイプに T
それも派生しています QObject
. 。さて、これが機能するためには、マクロです Q_OBJECT
クラスの定義に含める必要があります T
.
どうやら、 qt_check_for_QOBJECT_macro
呼び出しは、クラスにq_objectマクロが実際に含まれていることを確認するためです。マクロが拡張されると、次の定義が含まれています。
template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const
{ int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; }
template <typename T1, typename T2>
inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; }
したがって、オブジェクトがある場合 x
タイプの T
そしてオブジェクト y
タイプの U
, 、 呼び出し x->qt_check_for_QOBJECT_macro(y)
関数を呼び出します qYouForgotTheQ_OBJECT_Macro
タイプのパラメーター付き T*
と U*
. 。関数は単一のタイプパラメーターでテンプレートされているため、タイプ T
と U
同じでなければなりません。
今、あなたが電話するなら x->qt_check_for_QOBJECT_macro(x)
次に、タイプが同じであり、コンピレーションが簡単に成功することを期待する必要があります。ただし、それを覚えておいてください this
クラスと同じタイプを持っています方法は定義されていました。 x
Tから派生したが、それ自体の定義を含んでいないクラスのものです qt_check_for_QOBJECT_macro
, 、呼び出しが失敗します。
そのため、ターゲットタイプTに動的キャストの正しいメカニズムが含まれているかどうかを確認する方法がありますが、このメソッドを呼び出すタイプTのオブジェクトはまだありません。それがそうです reinterpret_cast<T>(0)
のためです。実際のオブジェクトは必要ありません this
, 、コンパイラは、チェックが成功するためにオブジェクトタイプのみを必要とするためです。代わりに、タイプTのヌルポインターのメソッドを呼び出します。
これはC ++標準では許可されていないと思いますが、それ以降は機能します this
メソッド内で実際には使用されていません。