Qt实现文件反射

目的

实现自动化处理, 通过配置文件即可提供实现对应功能处理。 但一个前提是, qt的是先已经注册了对应类, 然后才能通过对应配置文件中字符串转化为类。

代码

    QByteArray className = className.toUtf8() + "*";
    int id = QMetaType::type(className);
    if ( QMetaType::UnknownType == id ){
        return false;
    }

    const QMetaObject *metaObj = QMetaType::metaObjectForType(id);
    QObject *obj = metaObj->newInstance(Q_ARG(QWidget*, nullptr));
    xxxx *childObj= qobject_cast<xxxxx*>(obj);
    if(nullptr == childObj){
        qDebug()<<"can not find childObjin QMetaObject";
        return false;
    }

QMetaType

作用

QMetaType 是 Qt 获取有关类型的运行时动态信息的方法。它支持自定义类型的 QVariant 包装、QueuedConnection连接参数的副本等。

QMetaType在 Qt 4.0 中引入。它的创建是为了能够拥有异步信号和槽 ( Qt::QueuedConnection)。为了使排队槽发挥作用,我们必须复制参数并将它们存储在稍后处理的事件中。当我们完成调用槽时,我们还需要删除这些副本。(注意:使用时不需要Qt::DirectConnection:使用直接指向堆栈上参数的指针。)

调度信号的代码 有一个指向参数的指针数组, Qt 所知道的所有参数类型都是由 moc 提取的字符串名称。 QMetaObject::activate void*.

QMetaType提供了一种从字符串(例如"QPoint")获取复制或销毁对象的方法。然后,Qt 将使用void *QMetaType::create(int type, void *copy)和 QMetaType::destroy(int type, void *data)复制并销毁参数,其中 是使用参数的类型名称int type 获得的,如 moc 提供的。QMetaType::type(const char *typeName)QMetaType 还为开发人员提供了一种在元类型数据库中注册任何类型的方法。

QMetaType 的另一个用例是 QVariant。Qt 3.x 中的 QVariant 仅支持内置 Qt 类型,因为包含的任意类型也需要与包装 QVariant 一起复制或销毁。但在 QMetaType 的帮助下,QVariant 能够包含任何已注册的类型,因为 QVariant 现在可以复制和销毁所包含的对象实例。

保留信息

1、 注册的类型名称。有一个名称索引用于快速查找元类型 ID。从 Qt 4.7 开始,甚至可以用不同的名称注册相同的类型(对于 typedef 很有用)。
2、(复制)构造函数和析构函数(就地或非就地)。
3、Size了解为堆栈或内联成员构造分配多少空间。
4、 指定与 QTypeInfo(见下文)或转换类型相同的信息的标志。
5、 自定义转换函数,由QMetaType::registerConverter.
6、 QMetaObject,包含与类型关联的元 QObject 数据(如果存在)

QTypeInfo
QTypeInfo是一个与 QMetaType 正交的特征类,它允许开发人员手动指定(使用 )Q_DECLARE_TYPEINFO类型是可移动的(使用 memmove)或者是否需要运行其构造函数/析构函数。这主要用于 QVector 等容器中的优化。

由于内置类型和自定义类型之间存在很大差异。对于 QtCore 中的内置类型,每个元类型函数基本上都是一个开关,每个类型都有特殊的代码。在 Qt 5.0 中,这被重构以大量使用模板。 但是本文中我们感兴趣的是它如何用于自定义注册类型。

只有一个 保存所有信息和一堆函数指针的东西。QVector

Q_DECLARE_META_TYPE

QMetaTypeId该宏专门针对特定类型的模板类。
(事实上​​,它实际上专门化了该类QMetaTypeId2,并且大部分代码都使用 QMetaTypeId2。我不知道 QMetaTypeId2 背后的确切原因。也许这样 Qt 可以添加更多内置类型,而不会破坏以前使用的代码Q_DECLARE_METATYPE。)

QMetaTypeId用于在编译时确定类型的元类型 ID。
QMetaTypeId::qt_metatype_id是由 调用的函数qMetaType()。第一次调用该函数时,它将调用 QMetaType 中的某个内部函数,使用宏中指定的名称来注册并分配该类型的元类型 id。然后它将将该 id 存储在静态变量中。

除了名称之外,所有其他信息都是编译器使用模板自动推断的。

qRegisterMetaType

使用注册的类型Q_DECLARE_METATYPE将在第一次使用时实际注册(并分配一个 id)qMetaTypeId()。例如,当类型包装在 QVariant 中时就是这种情况。但在连接信号和槽时尚未注册。在这种情况下,您需要强制第一次使用 qRegisterMetaType

自动注册

开发人员经常忘记注册他们的元类型,直到他们看到编译错误或运行时错误告诉他们这样做。但如果没有必要那不是很好吗?唯一Q_DECLARE_METATYPE必要的原因是获得名字。但在某些情况下,我们可以在运行时知道名称,而无需使用该宏。例如,QList如果 T 已经注册,我们可以查询元类型系统并使用构造名称"QList<" + QMetaType::name(qMetaTypeId()) + “>”
我们对一堆模板化类执行此操作,例如:QList, QVector, QSharedPointer, QPointer, QMap, QHash, …
我们还可以确定指向 QObject 子类的指针的名称,这要归功于moc提供的信息: T::staticMetaObject.className() + “*”
从Qt 5.5开始,我们也会自动声明Q_GADGET和Q_ENUM。

这就是 的内容Q_DECLARE_METATYPE,但是您仍然需要调用qRegisterMetaType以在信号/槽排队连接中使用这些类型Q_PROPERTY或作为参数。qRegisterMetaType然而,从 Qt 5.x 开始,如果 moc 可以确定该类型可以注册为元类型,则由moc 生成的代码将调用您。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道阻且长,行则降至

无聊,打赏求刺激而已

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值