Qtを使い始めたばかりですが、すべてのサンプルクラス定義Q_OBJECT
の最初の行にマクロがあることに気付きました。このプリプロセッサマクロの目的は何ですか?
Qtを使い始めたばかりですが、すべてのサンプルクラス定義Q_OBJECT
の最初の行にマクロがあることに気付きました。このプリプロセッサマクロの目的は何ですか?
回答:
Qtドキュメントから:
メタオブジェクトコンパイラーmocは、QtのC ++拡張機能を処理するプログラムです。
mocツールはC ++ヘッダーファイルを読み取ります。Q_OBJECTマクロを含む1つ以上のクラス宣言が見つかると、それらのクラスのメタオブジェクトコードを含むC ++ソースファイルが生成されます。特に、シグナルとスロットのメカニズム、実行時の型情報、動的プロパティシステムにはメタオブジェクトコードが必要です。
Q_OBJECT::connect()
、むしろ単にconnect()
?
これは単に、このクラスにgui要素があり、 'moc'を実行する必要があることをプリコンパイラに通知するだけです。これは、シグナル/スロットメカニズムを使用するクラスに追加するだけです。
しかし、他のクラスでは静かに無視されます-ビルド時間を増やすだけです。
Q_OBJECT
中断しqobject_cast
ます。混乱を招く可能性があるため、お勧めできません。
Q_OBJECT
他の(非QObject
)クラスでは「静かに」無視されることは正しくありません。C ++標準によれば、定義されていないメンバー関数と変数を宣言することにより、未定義の動作を導入します。また、クラスQObject
固有のメンバーでクラスの名前空間を汚染します。たとえば、Q_OBJECT
と呼ばれるメソッドが含まれている無関係なクラスを破壊する可能性がありますmetaObject
。
Q_OBJECT
マクロを装備したいと思うかもしれませんが、マクロなしのgui-classesだけでなく、マクロ付きの非gui-classesを持つことは完全に理にかなっています。マクロは便利ですが、guiクラスに限定されず、必須でもありません。
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出力を含めるのを忘れています。
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 {};
Q_OBJECTマクロは、独自のシグナルとスロットを宣言する、またはQtのメタオブジェクトシステムによって提供される他のサービスを使用するクラス定義のプライベートセクションに表示する必要があります。
Q_OBJECT
マクロは、から派生するすべてのクラスに現れる必要がありますQObject
。マクロが存在しない場合、コードは微妙に破損します。また、たまたまコンパイルされたからといって、問題が発生することはありません。
Q_OBJECT
マクロが欠落しているときにコンパイルされても機能しないコードの例はありますか?
Q_OBJECT
アクセス指定子を使用していることがわかります。だから、マクロが下に表示されるべきかどうかprivate
、protected
またはpublic
指定子は無関係です-クラスの頭でそれを配置するだけの大会です。