メタ・オブジェクト・システム
Qtのメタオブジェクトシステムは、オブジェクト間通信のためのシグナルとスロットのメカニズム、ランタイム型情報、動的プロパティシステムを提供します。
メタオブジェクトシステムは以下の3つに基づいています:
- QObject クラスは、メタ・オブジェクト・システムを利用できるオブジェクトの基本クラスを提供する。
- Q_OBJECT マクロは、動的プロパティ、シグナル、スロットなどのメタオブジェクト機能を有効にするために使用されます。
- メタ・オブジェクト・コンパイラ(
moc
) は、各QObject サブクラスにメタ・オブジェクト機能を実装するために必要なコードを提供します。
moc
ツールは C++ ソース・ファイルを読み込みます。Q_OBJECT マクロを含むクラス宣言が 1 つ以上見つかれば、それらの各クラスのメタ オブジェクト・コードを含む別の C++ ソース・ファイルを生成します。この生成されたソース・ファイルは、#include
'dされてクラスのソース・ファイルに組み込まれるか、通常はコンパイルされてクラスの実装とリンクされます。
オブジェクト間の通信のためのシグナルとスロットのメカニズム(このシステムを導入した主な理由)を提供することに加えて、メタ・オブジェクト・コードは以下の追加機能を提供します:
- QObject::metaObject() は、クラスに関連するmeta-object を返します。
- QMetaObject::className()は、C++コンパイラによるネイティブ・ランタイム型情報(RTTI)サポートを必要とせずに、実行時にクラス名を文字列として返します。
- QObject::inherits() 関数は、オブジェクトがQObject 継承ツリー内で指定されたクラスを継承するクラスのインスタンスであるかどうかを返します。
- QObject::tr() は、国際化のために文字列を変換します。
- QObject::setProperty() およびQObject::property() は、名前によってプロパティを動的に設定および取得します。
- QMetaObject::newInstance() は、クラスの新しいインスタンスを構築します。
また、QObject クラスに対してqobject_cast() を使用してダイナミック・キャストを行うことも可能です。qobject_cast() 関数の動作は、標準 C++ のdynamic_cast()
と似ていますが、RTTI サポートが不要で、ダイナミック・ライブラリの境界を越えて動作するという利点があります。この関数は、角括弧で指定されたポインタ型に引数をキャストしようとし、オブジェクトの型が正しければ(実行時に決定される)0以外のポインタを返し、オブジェクトの型が互換性がなければnullptr
。
例えば、MyWidget
がQWidget を継承し、Q_OBJECT マクロで宣言されているとします:
QObject *obj = new MyWidget;
QObject *
型の変数obj
は、実際にはMyWidget
オブジェクトを参照しているので、適切にキャストできます:
オブジェクトは実際にはQWidget のサブクラスであるMyWidget
であるため、QObject からQWidget へのキャストは成功する。obj
はMyWidget
であることがわかっているため、MyWidget *
にもキャストできる:
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
qobject_cast() はQt組み込み型とカスタム型を区別しないので、MyWidget
へのキャストは成功します。
一方、QLabel へのキャストは失敗します。これにより、異なる型のオブジェクトを、型に応じて実行時に異なるように扱うことができます:
if (QLabel *label = qobject_cast<QLabel *>(obj)) { label->setText(tr("Ping")); } else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) { button->setText(tr("Pong!")); }
Q_OBJECT 、メタ・オブジェクト・コードなしでQObject を基本クラスとして使用することは可能ですが、Q_OBJECT マクロを使用しない場合、シグナルとスロット、およびここで説明するその他の機能は使用できません。メタ・オブジェクト・システムから見ると、メタ・コードを持たないQObject サブクラスは、メタ・オブジェクト・コードを持つ最も近い祖先と同等です。これはたとえば、QMetaObject::className() はあなたのクラスの実際の名前を返すのではなく、この祖先のクラス名を返すことを意味します。
したがって、QObject のすべてのサブクラスは、シグナル、スロット、プロパティを実際に使用するかどうかに関係なく、Q_OBJECT マクロを使用することを強くお勧めします。
QMetaObject 、Qtのプロパティシステム、シグナルとスロットも参照してください 。
本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。