• Qt 如何使用反射?


    Qt 如何使用反射?

    c++ 反射 标准库暂时还没有,那我们来看看如何使用 qt 来进行反射.

    反射类的案例

    1. 通过注册的类型需找 id 进行实例化该类

    myclass.h

    #include <QtCore>
    
    class MyClass
    {
    public:
        MyClass() {}
        QString name(){
            return "cheungxiongwei";
        }
    };
    //声明元对象类型
    Q_DECLARE_METATYPE(MyClass)
    

    main.cpp

    #include <QCoreApplication>
    #include "myclass.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        // 注册自定义的类
        qRegisterMetaType<MyClass>("MyClass");
    
        // 通过静态函数获取注册类的 id,id 不为 0 时,则获取成功.大部分基础类型都可以获取到 id,如 QString QByteArray
        int id = QMetaType::type("MyClass");
        if(id != 0){
            // 根据 id 创建该类型
            void *myClass = QMetaType::create(id);
            // 转换指针
            MyClass *my = static_cast<MyClass*>(myClass);
            // 调用函数
            qDebug() << my->name();
    
            // 这里可以添加一些自己自己的处理函数
    
            // 释放内存
            QMetaType::destroy(id, myClass);
            myClass = nullptr;
        }
    
        return a.exec();
    }
    

    2. 通过调用静态成员变量 MyClass::staticMetaObject 获取元对象信息,比较类名称来确定 QMetaObject

    myclass.h

    class MyClass1 : public QObject
    {
        Q_OBJECT
    public:
        Q_INVOKABLE MyClass1() {}
        virtual ~MyClass1() {}
        // 添加宏 Q_INVOKABLE 可以使用 invokeMethod 调用该函数
        Q_INVOKABLE QString name(QString name){
            return name.append("xiongwei");
        }
    
        QString name_(){
            return "cheungxiongwei";
        }
    };
    
    class MyClass2 : public QObject
    {
        Q_OBJECT
    public:
        MyClass2() {}
        virtual ~MyClass2() {}
    };
    
    inline QMetaObject GetMetaObjectByClassName(QString className)
    {
        QMetaObject metaObject;
        if(className.compare("MyClass1") == 0){
            metaObject = MyClass1::staticMetaObject;
        }else if (className.compare("MyClass2") == 0){
            metaObject = MyClass2::staticMetaObject;
        }
    
        // and so on, you get the idea ...
    
        return metaObject;
    }
    
    inline QMetaObject GetMetaObjectByClassName(QString className)
    {
        QMetaObject metaObject;
        if(className.compare("MyClass1") == 0){
            metaObject = LayoutCameraGrab::staticMetaObject;
        }else if (className.compare("MyClass2") == 0){
            metaObject = LayoutImageRead::staticMetaObject;
        }
    
        // and so on, you get the idea ...
    
        return metaObject;
    }
    
    inline void printMetaObject(const QMetaObject *metaObject)
    {
        qDebug() << "Class:" << metaObject->className();
        for(int i = 0;i < metaObject->classInfoCount();++i){
            qDebug() << "ClassInfo:" << metaObject->classInfo(i).name() << metaObject->classInfo(i).value();
        }
    
        for(int i = 0;i < metaObject->constructorCount();++i){
            qDebug() << "Constructor:" << metaObject->constructor(i).name() << metaObject->constructor(i).parameterNames();
        }
    
        for(int i = 0;i < metaObject->enumeratorCount();++i){
            qDebug() << "Enum:" << metaObject->enumerator(i).name();
        }
    
        for(int i = 0;i < metaObject->methodCount();++i){
            qDebug() << "Method:" << metaObject->method(i).name() << metaObject->method(i).parameterNames() << metaObject->method(i).tag();
        }
    
        for(int i = 0;i < metaObject->propertyCount();++i){
            qDebug() << "Proper:" << metaObject->property(i).name();
        }
    }
    

    main.cpp
    Note that only constructors that are declared with the Q_INVOKABLE modifier are made available through the meta-object system.
    上面一句话说的是只有在构造函数前面添加 Q_INVOKABLE 宏后才可以 QMetaObject 的函数 newInstance 创建该实例.

    #include <QCoreApplication>
    #include "myclass.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        // 通过类名称获取元对象类型
        QMetaObject metaObject = GetMetaObjectByClassName("MyClass1");
    
        // 实例化该类
        QObject *object = metaObject.newInstance();
        if(object){
            QString ret;
            // 调用 name 带参数函数
            // 如果未加 Q_INVOKABLE 宏,则输出 QMetaObject::invokeMethod: No such method MyClass1::name<QString>
            metaObject.invokeMethod(
                        object,
                        "name",
                        Qt::DirectConnection,
                        Q_RETURN_ARG(QString,ret),
                        Q_ARG(QString,"cheung"));
            // 打印返回值
            qDebug() << ret;
    
            // 转换指针类型调用未加 Q_INVOKABLE 宏的函数.
            MyClass1 *myclass = static_cast<MyClass1*>(object);
            Debug() << myclass->name_();
        }
    
        qDebug() << object;
    
        return a.exec();
    }
    
  • 相关阅读:
    Android ExpandableListView的下拉刷新实现
    Android 使用shape来画线
    三种常见的子查询(三十一)
    数据的准备(三十)
    LIMIT语句解析及本章简单回顾(二十九)
    WHERE、ORDER BY、GROUP BY、HAVING语句解析(二十八)
    查询表达式解析(二十七)
    单表的更新UPDATE和删除记录DELETE(二十六)
    插入记录INSERT(二十五)
    修改数据表——修改列定义和更名数据表(二十四)
  • 原文地址:https://www.cnblogs.com/cheungxiongwei/p/11780703.html
Copyright © 2020-2023  润新知