Qt

QTソースコード分析:qobject_cast



Qt Source Code Analysis



QT APIでのqobject_castの説明:

T qobject_cast(QObject * オブジェクト )。

指定されたを返します オブジェクト オブジェクトがタイプT(またはサブクラス)の場合はタイプTにキャストし、それ以外の場合は0を返します。 オブジェクト が0の場合、0も返します。



クラスTは(直接的または間接的に)継承する必要があります QObject と宣言されます Q_OBJECT 大きい。

クラスはそれ自体を継承すると見なされます。



例:

QObject *obj = new QTimer // QTimer inherits QObject QTimer *timer = qobject_cast(obj) // timer == (QObject *)obj QAbstractButton *button = qobject_cast(obj) // button == 0

qobject_cast()関数は、標準のC ++ dynamic_cast()と同様に動作しますが、RTTIサポートを必要とせず、ダイナミックライブラリの境界を越えて機能するという利点があります。



警告: Tがで宣言されていない場合 Q_OBJECT マクロの場合、この関数の戻り値は未定義です。

一般に、dynamic_castの代わりにqobject_castを使用することをお勧めします。 Xxx_cast(TB)、変換が成功するかどうかは、主にTA / TBがクラス継承システムにあるかどうか、およびTBがTAの同じタイプまたはサブクラスであるかどうかに依存します。 Dynamic_castはRTTIクラスの判断に依存しますが、qobject_castはQMetaObject情報に依存して決定します。ソースコードを見てみましょう:

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

|_+_|
  1. テンプレート <クラスT>
  2. 列をなしてT qobject_cast(QObject * object)
  3. {{
  4. #if!defined(QT_NO_MEMBER_TEMPLATES)&&!defined(QT_NO_QOBJECT_CHECK)
  5. reinterpret_cast(0)-> qt_check_for_QOBJECT_macro(*reinterpret_cast(目的語))
  6. //最初にマクロQ_OBJECTがクラスT定義で使用されているかどうかを確認します。使用する場合、qt_check_for_QOBJECT_macroには次の定義があります。
  7. //しかし、このマクロが使用されていない場合、操作は実際には意味がありません。Q_OBJECTが展開されているため、コンパイルエラーが発生します。
  8. //この関数の定義のみがあります
  9. #endif
  10. 戻る static_cast((reinterpret_cast(0)-> staticMetaObject.cast(object))
  11. //オブジェクトのメタ情報コードを実際に確認します。具体的には、次のQObject :: cast(QObject *)を確認します。ここでstaticMetaObject
  12. //は静的変数であるため、0アドレスをオブジェクトポインタとしてキャストするメソッドで呼び出すことができます。 0アドレスの使用でもあります。
  13. }
  14. テンプレート <クラスT>
  15. 列をなしてT qobject_cast(constQObject * object)
  16. {{
  17. // Tがconstでない場合、これによりコンパイルエラーが発生します
  18. 登録T ptr =static_cast(目的語)
  19. Q_UNUSED(ptr)
  20. #if!defined(QT_NO_MEMBER_TEMPLATES)&&!defined(QT_NO_QOBJECT_CHECK)
  21. reinterpret_cast(0)-> qt_check_for_QOBJECT_macro(*reinterpret_cast((const_cast(目的語)))
  22. #endif
  23. 戻る static_cast((const_cast((reinterpret_cast(0)-> staticMetaObject.cast(const_cast(目的語)))))
  24. }

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

  1. / *これは、qobject_castでキャストされたクラスを確認するコンパイル時のチェックです。
  2. 実際にはQ_OBJECTマクロが含まれています。注:QObjectの場合、qobject_castは失敗します
  3. サブクラスにQ_OBJECTが含まれていません。
  4. qt_check_for_QOBJECT_macroでは、2つのダミーテンプレート関数を呼び出します。
  5. パラメータ。最初は「this」で、もう1つはqobjectのターゲットです。
  6. キャスト。タイプが同一でない場合は、Q_OBJECTマクロが欠落していることがわかります。
  7. ここでコンパイラエラーが発生した場合は、キャストしているクラスを確認してください
  8. Q_OBJECTマクロを含みます。
  9. * /
  10. / * tmakeはQ_OBJECTを無視します* /
  11. #define Q_OBJECT_CHECK
  12. テンプレート <typenameT>列をなして ボイドqt_check_for_QOBJECT_macro(constT&_q_argument)const
  13. {{inti = qYouForgotTheQ_OBJECT_Macro(この、&​​_ q_argument)i = i}
  14. //この 'i = i'は追加のペンですか?誰かが私に言うために戸口を見たら、いいですか?
  15. //上記のコメントの2番目の段落はナンセンスではありませんか?この関数に入ることができるということは、Q_OBJECTがすでに使用されており、その目標を達成していることを示しています。
  16. テンプレート <typenameT>
  17. 列をなして intqYouForgotTheQ_OBJECT_Macro(T、T){戻る0}
  18. //役に立たない。
  19. テンプレート <typenameT1、typenameT2>
  20. 列をなして ボイドqYouForgotTheQ_OBJECT_Macro(T1、T2){}

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

  1. #define Q_OBJECT
  2. 公衆
  3. Q_OBJECT_CHECK //上記のいくつかの関数はこれを拡張したものです
  4. 静的 constQMetaObject staticMetaObject
  5. Q_OBJECT_GETSTATICMETAOBJECT
  6. バーチャル constQMetaObject * metaObject()const
  7. バーチャル ボイド* qt_metacast(const char*)
  8. QT_TR_FUNCTIONS
  9. バーチャル intqt_metacall(QMetaObject :: Call、intボイド**)
  10. 民間

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

  1. / *!
  2. 内部
  3. オブジェクト a objがこれを継承する場合、 aobjを返します
  4. それ以外の場合、メタオブジェクトは0を返します。
  5. * /
  6. QObject * QMetaObject :: cast(QObject * obj)const
  7. {{
  8. もし(obj){
  9. constQMetaObject * m = obj-> metaObject()
  10. 行う{{
  11. もし(m ==この)。
  12. 戻る const_cast(obj)
  13. }一方((m = m-> d.superdata))//メタオブジェクト情報の比較を通じて返されるコンテンツを決定します
  14. }
  15. 戻る0//対応するメタオブジェクト情報が継承システムに見つからない場合は、0を返します
  16. }

最後に、上記のqobject_castはダイナミックライブラリを通過できます。インターネットでこの文章を説明している人は見つかりませんでした。 QObjectやQWidgetなど、さまざまなダイナミックライブラリをサポートするオブジェクトを変換することを意味するのではないかと思います。もちろん、暗黙の条件は「変換されるオブジェクトであり、すべてQObjectのルートから継承されます」これは理解しやすいです。

上記はqobject_cast()に関連付けられたコードです。それを読んで、あなた自身の理解とあなたが理解していないことのいくつかを書いた後でも、利益はまだ素晴らしいです。ご不明な点がございましたら、訂正してください。

転載:https://blog.51cto.com/wilburwoo/595337