メタオブジェクトシステム

Qtのメタオブジェクトシステムは、オブジェクト間の通信のためのシグナルとスロットのメカニズム、実行時の型情報、および動的プロパティシステムを提供します。

メタオブジェクトシステムは、以下の3つの要素に基づいています:

  1. QObject クラスは、メタオブジェクトシステムを活用できるオブジェクトの基底クラスを提供します。
  2. Q_OBJECT マクロは、動的プロパティ、シグナル、スロットなどのメタオブジェクト機能を有効にするために使用されます。
  3. Meta-Object Compiler (moc) は、各 `QObject ` サブクラスに、メタオブジェクト機能を実装するために必要なコードを提供します。

moc ツールはC++ソースファイルを読み込みます。Q_OBJECT マクロを含むクラス宣言を1つ以上見つけた場合、それらの各クラスに対するメタオブジェクトコードを含む別のC++ソースファイルを生成します。この生成されたソースファイルは、#include によってクラスのソースファイルにインクルードされるか、あるいはより一般的な方法として、クラスの実装とともにコンパイルおよびリンクされます。

オブジェクト間の通信のためのシグナルとスロットのメカニズム(このシステムを導入した主な理由)を提供することに加え、メタオブジェクトコードは以下の追加機能も提供します:

  • 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 *widget = qobject_cast<QWidget *>(obj);

QObject からQWidget への型変換が成功するのは、そのオブジェクトが実際にはMyWidget であり、これはQWidget のサブクラスだからです。obj がMyWidget であることはわかっているため、これをMyWidget * に変換することもできます:

    MyWidget *myWidget = qobject_cast<MyWidget *>(obj);

MyWidget へのキャストが成功するのは、qobject_cast()がQtの組み込み型とカスタム型を区別しないためです。

    QLabel *label = qobject_cast<QLabel *>(obj);
    // label is nullptr

一方、QLabel への型変換は失敗します。その結果、ポインタはnullptr に設定されます。これにより、実行時に型に基づいて異なる型のオブジェクトをそれぞれ異なる方法で処理することが可能になります:

    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のプロパティシステム」、および「シグナルとスロット」も参照してください 。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.