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();
}
posted @ 2019-11-02 09:47  學海無涯  阅读(1133)  评论(0编辑  收藏  举报