Qt -元对象系统(Meta-Object System)

欢迎转载,请注明出处:https://blog.csdn.net/qq_39453936?spm=1010.2135.3001.5343
原文链接: https://blog.csdn.net/qq_39453936/article/details/120535137


一、基础组成

Qt 的元对象系统(Meta-Object System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。

  1. 类:QObject,为所有需要利用原对象系统的对象提供了一个基类。
  2. 宏:Q_OBJECT,通常可以声明在类的私有段中,让该类可以使用元对象对象的特性,比如动态属性,信号和槽。
  3. 编译器:元对象编译器(moc)为每个QObject子对象自动生成必要的代码来实现元对象特性。

构建项目时,MOC 工具读取 C++ 源文件,当它发现类的定义里有 Q_OBJECT 宏时,它就会为这个类生成另外一个包含有元对象支持代码的 C++ 源文件,这个生成的源文件连同类的实现文件一起被编译和连接。


二、功能特性

除了信号与槽机制外,元对象还提供如下一些功能:

  • QObject::metaObject() 函数返回类关联的元对象,元对象类 QMetaObject 包含了访问元对象的一些接口函数,例如 QMetaObject::className() 函数可在运行时返回类的名称字符串。

    QObject *obj = new QPushButton;
    obj->metaObject()->className (); //返回"QPushButton"
    
  • QObject::inherits(const char *className) 函数判断一个对象实例是否是名称为 className 的类或 QObject 的子类的实例。例如:

    QTimer *timer = new QTimer; // QTimer 是 QObject 的子类
    timer->inherits ("QTimer"); // 返回 true
    timer->inherits ("QObject");  // 返回 true
    timer->inherits ("QAbstractButton");//返回 false,不是 QAbstractButton 的子类
    
  • QObject::tr() 和 QObject::trUtf8() 函数可翻译字符串,用于多语言界面设计,后续章会专门介绍多语言界面设计。

  • QObject::setProperty() 和 QObject::property() 函数用于通过属性名称动态设置和获取属性值。

  • QMetaObject::newInstance() 函数创建类的一个新的实例。

  • 对于 QObject 及其子类,还可以使用 qobject_cast() 函数进行动态投射,qobject_cast()方法的功能类似于标准C++的dynamic_cast(),但qobject_cast()不需要RTTI的支持。,例如:

    //假设MyWidget继承自QWidget,同时也声明了Q_OBJECT宏,
         QObject *obj = new MyWidget;
    //QObject类型的变量obj实际上指向一个MyWidget对象,进行类型转换:
         QWidget *widget = qobject_cast<QWidget *>(obj);//得到widget 
        
         //如果
         QLabel *label = qobject_cast<QLabel *>(obj);// label is 0
    //QLabel的转型会失败,指针会被设置为0。这样使得我们可以在运行时根据对象类型,对不同类型的对象进行不同的处理:
       if (QLabel *label = qobject_cast<QLabel *>(obj)) 
       {
           label->setText(tr("label"));
       } 
       else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) 				
       {
           button->setText(tr("QPushButton"));
       }
    

    如果我们只是单纯的使用QObject作为基类,不用Q_OBJECT宏和原对象信息,那么信号和槽以及其他这里描述的特性将无法使用。从元对象系统的观点来看,一个没有元对象代码的QObject子类和其最接近的有元对象代码的祖先是等同的。这也就意味着,QMetaObject::className()将不会返回你的类的真实的名字,而是该类某一个祖先的名字。建议:所有QObject的子类都是用Q_OBJECT宏,不管你实际上是否使用信号和槽,以及属性。


三、属性系统

#ifndef OBJECT_H
#define OBJECT_H
class Object : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int age READ age  WRITE setAge NOTIFY ageChanged)
    Q_PROPERTY(int score READ score  WRITE setScore NOTIFY scoreChanged)
    Q_CLASSINFO("Author", "Scorpio")
    Q_CLASSINFO("Version", "1.0")
    Q_ENUMS(Level)
};
#endif // OBJECT_H

Q_PROPERTY()

在 QObject 的子类中,用宏 Q_PROPERTY() 定义属性,其使用格式如下:

 Q_PROPERTY(type name
         (READ getFunction [WRITE setFunction] |
          MEMBER memberName [(READ getFunction | WRITE setFunction)])
         [RESET resetFunction]
         [NOTIFY notifySignal]
         [REVISION int]
         [DESIGNABLE bool]
         [SCRIPTABLE bool]
         [STORED bool]
         [USER bool]
         [CONSTANT]
         [FINAL])
  • Type:属性的类型
  • Name:属性的名称
  • READ getFunction:属性的访问函数
  • WRITE setFunction:属性的设置函数
  • RESET resetFunction:可选,用于指定一个设置属性缺省值的函数
  • NOTIFY notifySignal:,可选,用于属性发生变化的地方发射的notifySignal信号
  • REVISION int:属性的版本,属性暴露到QML中
  • DESIGNABLE bool:属性在GUI设计器Qt Designer中是否可见,默认为true
  • SCRIPTABLE bool:属性是否可以被脚本引擎访问,默认为true
  • STORED bool:表示是否应将属性视为独立存在或取决于其他值,大多数属性都是存储的(默认为true),但例如,QWidget::minimumWidth()存储了false,因为它的值只是从属性QWidget::minimumSize()的宽度组件中获取的。
  • USER bool:属性是否可编辑的属性。通常,每个类只有一个用户属性(默认为false)。 例如QAbstractButton::checked是按钮的用户可编辑属性。
  • CONSTANT:标识属性的值是常量,值为常量的属性没有WRITE、NOTIFY
  • FINAL:标识属性不会被被子类重载

Q_PROPERTY 宏定义一个返回值类型为 type,名称为 name 的属性,用 READ、WRITE 关键字定义属性的读取、写入函数,还有其他的一些关键字定义属性的一些操作特性。属性的类型可以是 QVariant 支持的任何类型,也可以用户自定义类型。

Q_CLASSINFO()

可以为类的元对象定义“名称——值”;
用 Q_CLASSINFO() 宏定义附加类信息后,可以通过元对象的一些函数获取类的附加信息,如 classlnfo(int) 获取某个附加信息,函数原型定义如下:

QMetaClassInfo QMetaObject::classInfo(int index) const

返回值是 QMetaClassInfo 类型,有 name() 和 value() 两个函数,可获得类附加信息的名称和值。

Q_INVOKABLE

Q_INVOKABLE宏用于定义一个成员函数可以被元对象系统调用,Q_INVOKABLE宏必须写在函数的返回类型之前。如下:
Q_INVOKABLE void invokableMethod();
invokableMethod()函数使用了Q_INVOKABLE宏声明,invokableMethod()函数会被注册到元对象系统中,可以使用 QMetaObject::invokeMethod()调用。
Q_INVOKABLE与QMetaObject::invokeMethod均由元对象系统唤起。


参见 https://blog.51cto.com/u_9291927/2070348

小白发文,不喜勿喷

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值