Q_OBJECTマクロは何をしますか?すべてのQtオブジェクトにこのマクロが必要なのはなぜですか?


131

Qtを使い始めたばかりですが、すべてのサンプルクラス定義Q_OBJECTの最初の行にマクロがあることに気付きました。このプリプロセッサマクロの目的は何ですか?


25
QTはQuickTimeを指し、QtはQtと呼ばれるC ++ライブラリを指します。
Bleadof 2009

回答:


132

Qtドキュメントから:

メタオブジェクトコンパイラーmocは、QtのC ++拡張機能を処理するプログラムです。

mocツールはC ++ヘッダーファイルを読み取ります。Q_OBJECTマクロを含む1つ以上のクラス宣言が見つかると、それらのクラスのメタオブジェクトコードを含むC ++ソースファイルが生成されます。特に、シグナルとスロットのメカニズム、実行時の型情報、動的プロパティシステムにはメタオブジェクトコードが必要です。


明示的に書く必要がないのはなぜですか Q_OBJECT::connect()、むしろ単にconnect()
mLstudent33

19

これは単に、このクラスにgui要素があり、 'moc'を実行する必要があることをプリコンパイラに通知するだけです。これは、シグナル/スロットメカニズムを使用するクラスに追加するだけです。
しかし、他のクラスでは静かに無視されます-ビルド時間を増やすだけです。


3
また、シグナル/スロットメカニズムを使用するクラスでのみ必要であることも誤りです。の欠如は、内省をQ_OBJECT中断しqobject_castます。混乱を招く可能性があるため、お勧めできません。
モニカを

2
Q_OBJECT他の(非QObject)クラスでは「静かに」無視されることは正しくありません。C ++標準によれば、定義されていないメンバー関数と変数を宣言することにより、未定義の動作を導入します。また、クラスQObject固有のメンバーでクラスの名前空間を汚染します。たとえば、Q_OBJECTと呼ばれるメソッドが含まれている無関係なクラスを破壊する可能性がありますmetaObject
モニカ

2
それは間違っている。ほとんどのgui-classesにQ_OBJECTマクロを装備したいと思うかもしれませんが、マクロなしのgui-classesだけでなく、マクロ付きの非gui-classesを持つことは完全に理にかなっています。マクロは便利ですが、guiクラスに限定されず、必須でもありません。
pasbi

9

MOC(メタオブジェクトコンパイラ)は、Q_OBJECTマクロを含むヘッダーファイルをC ++の同等のソースコードに変換します。それは基本的にシグナルスロットメカニズムを制御し、C ++コンパイラに理解可能にします


2
それは誤りです。Q_OBJECTマクロはコンパイラーによって展開され、mocは必要ありません。mocはマクロ自体には何もしませんが、マクロが宣言したメンバー変数とメソッドの定義を生成ます。Q_OBJECT
モニカ

5

1 メタオブジェクトシステムの Qtドキュメントから

mocツールはC ++ソースファイルを読み取ります。Q_OBJECTマクロを含む1つ以上のクラス宣言が見つかると、それらのクラスのそれぞれのメタオブジェクトコードを含む別のC ++ソースファイルが作成されます。この生成されたソースファイルは、クラスのソースファイルに#includeされるか、通常はコンパイルされてクラスの実装にリンクされます。

2 QtドキュメントのTHE Q_OBJECTから

Q_OBJECTマクロは、独自のシグナルとスロットを宣言する、またはQtのメタオブジェクトシステムによって提供される他のサービスを使用するクラス定義のプライベートセクションに表示する必要があります。

3 mocの Qtドキュメントから

mocツールはC ++ヘッダーファイルを読み取ります。Q_OBJECTマクロを含む1つ以上のクラス宣言が見つかると、それらのクラスのメタオブジェクトコードを含むC ++ソースファイルが生成されます。特に、シグナルとスロットのメカニズム、実行時の型情報、動的プロパティシステムにはメタオブジェクトコードが必要です。

4 信号とスロットの Qtドキュメントから

Q_OBJECTマクロは、mocによって実装されるいくつかのメンバー関数を宣言するためにプリプロセッサーによって展開されます。「LcdNumberのvtableへの未定義の参照」の行に沿ってコンパイラエラーが発生した場合は、おそらくmocを実行するか、リンクコマンドにmoc出力を含めるのを忘れています。


2

gccでは、-E展開されたマクロを確認できます。これはQ_OBJECT、Linuxのgccに拡張されます。これはプラットフォームに依存している可能性があり、QTのバージョンによって異なる場合があることに注意してください。これはmocコンパイラーの単なるタグではないことがわかります。

# 11 "mainwindow.hh"
#pragma GCC diagnostic push
# 11 "mainwindow.hh"

# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wsuggest-override"
# 11 "mainwindow.hh"
    static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, cons
t char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } __attribute__ ((__deprecated__)) static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private:
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wattributes"
# 11 "mainwindow.hh"
    __attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
# 11 "mainwindow.hh"
#pragma GCC diagnostic pop
# 11 "mainwindow.hh"
    struct QPrivateSignal {};

0

Q_OBJECTマクロは、独自のシグナルとスロットを宣言する、またはQtのメタオブジェクトシステムによって提供される他のサービスを使用するクラス定義のプライベートセクションに表示する必要があります。


1
これは誤解を招く可能性があります。Q_OBJECTマクロは、から派生するすべてのクラスに現れる必要がありますQObject。マクロが存在しない場合、コードは微妙に破損します。また、たまたまコンパイルされたからといって、問題が発生することはありません。
モニカ

@KubaOber Q_OBJECTマクロが欠落しているときにコンパイルされても機能しないコードの例はありますか?
クリス

2
の実装を見ると、Q_OBJECTアクセス指定子を使用していることがわかります。だから、マクロが下に表示されるべきかどうかprivateprotectedまたはpublic指定子は無関係です-クラスの頭でそれを配置するだけの大会です。
TrebledJ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.