40

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))));
}

誰か説明したいですか?

4

1 に答える 1

38

これは少し複雑です...

これは、もから派生するターゲットタイプqobject_cast<T>(obj)に動的にキャストする方法であることを忘れないでください。これが機能するためには、マクロをクラスの定義に含める必要があります。QObjectTQObjectQ_OBJECTT

どうやら、この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はタイプとのパラメーターを使用して関数を呼び出します。関数は単一の型パラメーターでテンプレート化されているため、型とは同じである必要があります。yUx->qt_check_for_QOBJECT_macro(y)qYouForgotTheQ_OBJECT_MacroT*U*TU

ここで、を呼び出す場合x->qt_check_for_QOBJECT_macro(x)は、型が同じであり、コンパイルが簡単に成功することを期待する必要があります。ただし、thisはメソッドが定義されたクラスと同じタイプであることに注意してください。したがって、xがTから派生したクラスであるが、独自の定義が含まれていない場合qt_check_for_QOBJECT_macro、呼び出しは失敗します。

したがって、ターゲットタイプTに動的キャストの正しいメカニズムが含まれているかどうかを確認する方法はありますが、このメソッドを呼び出すタイプTのオブジェクトはまだありません。それreinterpret_cast<T>(0)が目的です。thisコンパイラはチェックが成功するためにオブジェクトタイプのみを必要とするため、実際のオブジェクトは必要ありません。代わりに、タイプTのnullポインターでメソッドを呼び出します。

これはC++標準では許可されていないと思いますがthis、メソッド内で実際に使用されていないため、機能します。

于 2010-12-23T11:32:23.210 に答える