Qt オブジェクト モデル: オブジェクト ツリーとメタオブジェクト システム

1. オブジェクトツリーの概念

Qt はオブジェクト ツリー (オブジェクト ツリー) を使用して、QObject クラスとそのサブクラスのすべてのオブジェクトを整理および管理します。QObject を作成するときに、他のオブジェクトがその親オブジェクト (parent) として使用されている場合、この QObject は親オブジェクトの Children() リストに追加されます。そのため、親オブジェクトが破棄されると、この QObject も破棄されます。 。実際にやってみると、このメカニズムは GUI オブジェクトの管理に非常に適していることがわかります。たとえば、QShortcut (キーボード ショートカット) オブジェクトは対応するウィンドウの子であるため、ユーザーがウィンドウを閉じるとショートカットも破棄できます。

QWidget は、画面上に表示できるすべてのコンポーネントの基本クラスとして、オブジェクト間の親子関係を拡張します。子オブジェクトは親ウィジェットの領域に表示されるため、通常は子ウィジェットでもあります。たとえば、メッセージ ボックスを閉じて破棄すると、メッセージ ボックス内のボタンとラベルも破棄されますが、ボタンとラベルはメッセージ ボックスの子であるため、これはまさに私たちが望んでいることです。もちろん、子オブジェクトを自分で破棄することもできます。この部分については、ヘルプ索引の「オブジェクト ツリーと所有権」キーワードを参照してください。

この記事の利点は、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、Qt プログラミング入門、QT シグナルおよびスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT データベース プログラミング、QTプロジェクトコンバット、QSS、OpenCV、クイックモジュール、インタビューの質問など) ↓↓↓↓下記を参照↓↓記事下部をクリックして料金を受け取ります↓↓

2. オブジェクトツリーのプログラム例

新しい Qt Gui アプリケーションを作成します。プロジェクト名は myOwnership、基本クラスは QWidget、クラス名は Widget のままです。完了後、新しいファイルをプロジェクトに追加し、テンプレートとして C++ クラスを選択します。クラス名は MyButton、基本クラスは QPushButton、型情報は「QWidget から継承」を選択します。ファイルを追加した後、mybuuon.h ファイルを次のように変更します。

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QPushButton>
#include <QDebug>

class MyButton : public QPushButton
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);
    ~MyButton();
};

#endif // MYBUTTON_H

これは主にデストラクタの宣言を追加するためのものです。次に、mybutton.cpp ファイルに移動し、次のように変更します。

#include "mybutton.h"

MyButton::MyButton(QWidget *parent) :
    QPushButton(parent)
{
}

MyButton::~MyButton()
{
    qDebug() << "delete button";
}

ここにデストラクタの定義を追加し、MyButtonのオブジェクトが破棄された際に、対応する情報が出力されるようにします。

次に、widget.cpp ファイルに移動し、次のように変更します。

#include "widget.h"
#include "ui_widget.h"
#include "mybutton.h"
#include <QDebug>
#include <QHBoxLayout>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建按钮部件,指定widget为父部件
    MyButton *button = new MyButton(this);
    button->setText(tr("button"));
}

Widget::~Widget()
{
    delete ui;
    qDebug() << "delete widget";
}

Widgetウィンドウが破壊されるとメッセージが出力されます。以下のプログラムを実行してウィンドウを閉じると、Qt Creator のアプリケーション出力列の出力情報は次のようになります。

delete widget
delete button

ウィンドウが閉じられると、ウィンドウはトップレベル ウィンドウであるため、アプリケーションはウィジェットを破棄することがわかります (トップレベル ウィンドウでない場合、ウィジェットは閉じたときにのみ非表示になり、実際には非表示にはなりません)破棄されます)、ウィジェットが破棄されると、そのサブアセンブリも自動的に破棄されます。Qt では、多くの場合、新しい操作のみが表示され、削除操作は表示されないのはこのためです。

ウィジェット オブジェクトがスタック上に構築されている main.cpp ファイルをもう一度見てみましょう。

Widget w;
w.show();

このようにして、オブジェクト w はプログラムを閉じるときに自動的に破棄されます。ウィジェット内のコンポーネントについては、(new 演算子を使用して) ヒープ上に作成されている場合は、ウィジェットを親ウィンドウとして指定するだけでよく、削除操作は必要ありません。オブジェクト w が破棄されると、そのすべてのサブコンポーネントが自動的に破棄されます。これは Qt のオブジェクト ツリーによって行われます。

したがって、標準の Qt プログラムの場合、メイン ウィジェットを (new 演算子を使用して) ヒープ上に作成するのではなく、main() 関数のスタック上に作成する必要があります (「Widget w;」など)。他のウィジェットの場合、new 演算子を使用してヒープ上に作成できますが、オブジェクトを破棄するために delete 演算子を使用する必要がないように、その親ウィジェットを指定する必要があります。

3. メタオブジェクトシステムの概念

Qt のメタオブジェクト システムは、オブジェクト間通信のためのシグナルおよびスロット メカニズム、ランタイム型情報、および動的プロパティ システムを提供します。メタオブジェクト システムは次の 3 つの条件に基づいています。

  • このクラスは QObject クラスを継承する必要があります。
  • Q_OBJECT マクロは、クラスのプライベート宣言領域で宣言する必要があります (クラスの定義時に、パブリックまたはプライベートが指定されていない場合、デフォルトはプライベートです)。
  • メタオブジェクト コンパイラー Meta-Object Compiler (moc) は、QObject のサブクラスがメタオブジェクト機能を実装するために必要なコードを提供します。

その中で、moc ツールは C++ ソース ファイルを読み取り、1 つ以上のクラス宣言に Q_OBJECT マクロが含まれていることが判明すると、別の C++ ソース ファイルを作成します (つまり、プロジェクト ディレクトリのデバッグ ディレクトリの下に表示されます)。 moc で始まる C++ ソース ファイル)。これには、各クラスに対して生成されたメタオブジェクト コードが含まれます。これらの生成されたソース ファイルは、クラスのソース ファイルに組み込まれるか、クラスの実装と同時にコンパイルおよびリンクされます。

メタオブジェクト システムは、主に信号とスロットのメカニズムを実装するために導入されましたが、信号とスロットのメカニズムに加えて、メタオブジェクト システムは他のいくつかの機能も提供します。

  • QObjeCt::metaObject() 関数は、QMetaObject クラスのオブジェクトであるクラスのメタ オブジェクトを返すことができます。
  • QMetaObject::className() は、C++ エディターのネイティブ ランタイム型情報 (RTTI) のサポートなしで、実行時にクラス名を文字列として返すことができます。
  • QObject:: "inherits() 関数は、オブジェクトが QObject 継承ツリー上のクラスのインスタンスであるかどうかに関する情報を返します。
  • QObject::tr() と QObject::trUtf8() は国際化のための文字列変換を実行します。
  • QObject::setProperty() および QObject::property() は、名前によってオブジェクトのプロパティを動的に設定または取得します。
  • QMetaObject: :newlnstance() このクラスの新しいインスタンスを構築します。

これらの機能に加えて、qobject_cast() 関数を使用して QObject クラスで動的型変換を実行することもできます。この関数の関数は標準 C++ のdynamic_cast() 関数に似ていますが、RTTI サポートは必要なくなりました。この関数は、引数を山かっこで囲まれた型のポインターに変換しようとします。正しい型の場合は 0 以外のポインターを返し、型に互換性がない場合は 0 を返します。例えば:

QObject *obj = new MyWidget;
QWidget *widget = qobject_cast<QWidget *>(obj);

シグナルとスロットのメカニズムは Qt の中核的なコンテンツであり、シグナルとスロットのメカニズムはメタオブジェクト システムに依存する必要があるため、Qt の重要なコンテンツです。ここではそのアプリケーションの一部を説明するだけであり、その具体的な実装メカニズムについてはここでは説明しません。メタ オブジェクト システムの具体的な説明については、Qt の The Meta Object System キーワードを参照してください。

記事はブログガーデン(fengMisaka)より転載:https://www.cnblogs.com/linuxAndMcu/p/11026850.html

 この記事の利点は、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、Qt プログラミング入門、QT シグナルおよびスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT データベース プログラミング、QTプロジェクトコンバット、QSS、OpenCV、クイックモジュール、インタビューの質問など) ↓↓↓↓下記を参照↓↓記事下部をクリックして料金を受け取ります↓↓

おすすめ

転載: blog.csdn.net/QtCompany/article/details/131794829