Qt6入门教程 6:Qt元对象系统

目录

一.什么是Qt元对象系统?

[二.编译时Qt Creator偷摸做了哪些事情?](#二.编译时Qt Creator偷摸做了哪些事情?)

1.uic

2.rcc

3.moc


一.什么是Qt元对象系统?

Qt中的元对象系统(Meta-Object System)提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。元对象系统是基于以下3个条件的:

●该类必须继承自QObject类;

●必须在类的私有声明区声明Q_OBJECT宏(在类定义时,如果没有指定public或者private,则默认为private);

●元对象编译器Meta-Object Compiler(moc),为QObject的子类实现元对象特性提供必要的代码。

其中,moc工具读取一个C++源文件,如果它发现一个或者多个类的声明中包含有Q_OBJECT宏,便会另外创建一个C++源文件(就是在项目目录中的debug或release目录下看到的以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。

例如:

cpp 复制代码
QObject *obj = new MyWidget;
QWidget *widget = qobject_cast<QWidget *>(obj);

另外,一个没有定义 Q_OBJECT 宏的类与它最接近的父类是同一类型的。也就是说,如果 A 继承了 QObject 并且定义了 Q_OBJECT,B 继承了 A 但没有定义 Q_OBJECT,C 继承了 B,则 C 的 QMetaObject::className() 函数将返回 A,而不是本身的名字。因此,为了避免这一问题,所有继承了 QObject 的类都应该定义 Q_OBJECT 宏,不管你是不是使用信号槽。

关于元对象系统,详见:Qt Assistant--->The Meta Object System关键字。

信号和槽机制是Qt的核心内容,它依赖于元对象系统,将在下一篇中介绍。

二.编译时Qt Creator偷摸做了哪些事情?

结合前面几篇博文,我们看看编译时Qt Creator偷摸做了哪些事情:

1.uic

User Interface Compiler,它读取Qt Designer创建的XML格式的user interface definition(.ui)文件,生成对应的C++头文件(以ui_为前缀)

.ui文件存在的意义是让界面和业务分离,这样UI设计工程师可以用Qt Designer专心的设计界面,而不用关系业务逻辑。那么.ui文件最后是如何根 C++业务代码关联起来的呢?ui_xxxx.cpp文件中的setupUi函数便是桥梁。

以前面HelloWorld项目中的MainWindow类为例:

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
   // 添加标题栏图标
    setWindowIcon(QIcon(":/icons/AppIcon.ico"));
}
 
MainWindow::~MainWindow()
{
    delete ui;
}

在构造函数中我们调用了ui对象的setupUi方法,并传入MainWindow类的指针;在析构函数中将ui对象删除。

切换到mainwinows.h

cpp 复制代码
#include <QMainWindow>
 
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
 
class MainWindow : public QMainWindow
{
  Q_OBJECT
 
public:
  MainWindow(QWidget *parent = nullptr);
  ~MainWindow();
 
private:
  Ui::MainWindow *ui;
};

namespace Ui { class MainWindow; }是前缀声明,这样就可以用Ui::MainWindow声明指针变量ui:

cpp 复制代码
Ui::MainWindow *ui;

而Ui { class MainWindow; }中的MainWindow正是ui_mainwindow.h中Ui_MainWindow类的子类,因此在调用setupUi后,就能用ui访问界面的控件了。

cpp 复制代码
#ifndef UI_MAINWINDOW_H  
#define UI_MAINWINDOW_H  
 
QT_BEGIN_NAMESPACE 
class Ui_MainWindow  
{  
public:  
    // 一些控件对象的声明
    ......
    void setupUi(QMainWindow *MainWindow)  
    {  
         // 一些控件对象的定义
         ......
    } // setupUi  
    ......
};  
 
namespace Ui {  
     class MainWindow: public Ui_MainWindow {};  
} // namespace Ui  
 
QT_END_NAMESPACE  
#endif // UI_MAINWINDOW_H 

2.rcc

Resource Compiler,用于在编译时将资源嵌入到Qt程序中,它读取XML格式的Qt resource(.qrc)文件,生成一个包含资源数据的C++源文件(以qrc_为前缀)

3.moc

Meta-Object Compiler,用于读取一个C++源文件,如果它发现一个或者多个类的声明中包含有Q_OBJECT宏,便会另外创建一个C++源文件(以moc_为前缀)

uic.exe、rcc.exe和moc.exe都在Qt的安装目录中,自己找找吧!

原文链接:Qt6入门教程 6:Qt元对象系统-CSDN博客

相关推荐
Web极客码23 分钟前
Python Ollama 本地 Agent 入门与订单查询实践
开发语言·jvm·python
kimnoic1 小时前
PHP 8.2的DNF类型怎么用才规范
开发语言·php
_Evan_Yao1 小时前
前后端联调怎么排查问题?从 Network 到后端日志,一步步定位错误
开发语言·后端·团队开发·需求分析
hudd6681 小时前
JavaEE 初阶 - 多线程(进阶)
java·开发语言·java-ee
小白快快跑哦2 小时前
python-字符串全解(六):正则表达式-前后相断言
开发语言·python·正则表达式·前后相断言
kimnoic2 小时前
Python数据分析中正则表达式匹配字符串与常用函数示例详解
开发语言·python
中屹指纹浏览器svip2 小时前
打开账号环境网页报错,常见原因有哪些?
服务器·开发语言·php·中屹指纹浏览器
朝朝辞暮i2 小时前
第 01 讲:Python 变量、对象、数据类型与内存引用
开发语言·python
外收内放2 小时前
Python基础语法练习题(69)
开发语言·python
lojox2 小时前
深入理解 C++ STL:vector 底层实现、迭代器失效与 list 特性
开发语言·c++