Qt学习笔记 01 - Meta data 和 内存管理

这篇博客介绍了Qt中的QObject基类及其特性,强调QObject系列类不支持拷贝构造和赋值操作。重点讲解了Meta data,包括类名、继承、属性、信号和槽,特别是属性的使用,通过宏定义在编译时收集属性信息。示例代码展示了如何应用Q_OBJECT宏声明信号与槽。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.QObject

QObject是绝大多数Qt类的基类, 也有些类不是继承的他

  • 需要轻量级实现的类 如(QPoint QRect QColor QBrush...等)
  • 数据容器 (QString QList  QChar)
  • 可拷贝的类..                                                                         PS:言外之意 QObject 系列都是不能 拷贝构造 或者赋值的,这种界面类复制一个确实很奇怪

2.Meta data

主要包含了

  • 类名(QObject::className)
  • 继承(QObject::inherits)                                                       
  • 属性(QObject::properties)
  • 信号和槽
  • 类信息

今天主要学了 属性,属性就是 用一些宏,在来控制,在编译时收集获取的属性信息

Demo

 

valueobject.h

#ifndef VALUEOBJECT_H
#define VALUEOBJECT_H
#include <QObject>
#include <QDebug>


class ValueObject : public QObject
{
    Q_OBJECT  //编译时收集类信息

    /*设置类信息的宏
     *在程序中可以使用相应函数获取设置的信息
     */
    Q_ENUMS(week)                               //PS: 枚举类型必须为公有

    /*
      Q_PROPERTY(type name
                 READ getFunction
                 [WRITE setFunction]
                 [RESET resetFunction]
                 [DESIGNABLE bool]
                 [SCRIPTABLE bool]
                 [STORED bool]
                 [USER bool])
    */

    Q_PROPERTY(int  valueInt                    
               READ value                       
               WRITE setValue
               )



public:
    ValueObject(QObject* parent=0);

    int value(void) const
    {
        return m_value;
    }

    ~ValueObject();
    enum week{A1,A2,A3} ;

public slots:
    void setValue(int v)
    {
        if( v != m_value ) /*避免死循环*/
        {
            qDebug()<<this->objectName()<<"m_value "<<m_value<<"change to"<<v;
            m_value = v;
            emit valueChange(m_value);
        }
    }

private:
    int m_value;

signals:
    void valueChange(int v);
};

#endif // VALUEOBJECT_H


 

valueobject.cpp

 

#include "valueobject.h"

ValueObject::ValueObject(QObject* parent):QObject(parent),m_value(0)
{

}
ValueObject::~ValueObject()
{
    qDebug()<<this->objectName()<<" destruct";
}


main.cpp
#include <QtCore/QCoreApplication>
#include "valueobject.h"

#include <QDebug>
#include <QtCore>


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ValueObject v;
    bool ok = false;

    QVariant s;

    qDebug()<<v.inherits("QObject")         /*检测是否具有继承关系*/
            <<v.inherits("ValueObject");

    int index = v.metaObject()->indexOfEnumerator("week");  /*获取类信息 [枚举类型列表]index 供 enumerator()索引*/

    /*----------------------------------------------------------
     *   PS: Q_ENUMS连续设置多个 编号则0~n 用 enumerator(int index)
     *       索引出 QMetaEnum 对象
     *       然后 QMetaEnum().key(int index) 返回枚举相应名字符串指针
     *---------------------------------------------------------*/
    qDebug()<<(v.metaObject()->enumerator(index).key(1));

    /*---------------------------------------------------------
     *  property("属性名")      调用 Q_PROPERTY 设置的 READ  函数
     *  setProperty("属性名",v) 调用 Q_PROPERTY 设置的 WRITE 函数
     *  设置时类型不匹配返回 false
     *  设置时诺属性不存在则返回 false 动态添加该属性
     *  PS:同样可以用 int index 进行索引, propertyCount() 返回属性
     *  个数
     *--------------------------------------------------------*/
    qDebug()<<v.property("valueInt").toInt(&ok);
    qDebug()<<ok;

    v.setProperty("valueInt",777);
    qDebug()<<v.property("valueInt").toInt(&ok);
    qDebug()<<ok;

    /*----------------------------------------------------------
     *  测试父子对象内存管理
     *---------------------------------------------------------*/
    ValueObject* parent = new ValueObject();
    parent->setObjectName("parent");

    ValueObject* child1 = new ValueObject(parent);
    child1->setObjectName("child1");

    ValueObject* child2 = new ValueObject(parent);
    child2->setObjectName("child2");

    ValueObject* c1s_chiled1 = new ValueObject(child1);
    c1s_chiled1->setObjectName("c1s_chiled1");

    ValueObject* c1s_chiled2 = new ValueObject(child1);
    c1s_chiled2->setObjectName("c1s_chiled2");

    ValueObject* c2s_chiled1 = new ValueObject(child2);
    c2s_chiled1->setObjectName("c2s_chiled1");

    ValueObject c2s_chiled2(child2);
    c2s_chiled2.setObjectName("c2s_chiled2");

    delete parent;

    /*
     *  测试交互
     */

    ValueObject s1,s2;
    s1.setObjectName("s1");
    s2.setObjectName("s2");

    QObject::connect(&s1,SIGNAL(valueChange(int)),      /*PS: connect 为 QObject 静态成员函数,非静态也有...*/
                     &s2,SLOT(setValue(int)));

    s2.connect(&s2,SIGNAL(valueChange(int)),
                     &s1,SLOT(setValue(int)));

    s1.setValue(7);
    s2.setValue(17);

    int ret = a.exec();

    return ret;
}


 


 

Q_OBJECT

使用信号与槽的类在类的声明中都必须加上Q_OBJECT宏,表示使用元对象系统,Q_OBJECT列出元对象的声明、类名、属性函数、字符串翻译函数等。Q_OBJECT的宏定义列出如下(在src/kernel/qobjectdefs.h中):

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值