• Qt类反射机制


    前言
     
    如何通过类名动态的创建对象(类反射),对于Java开发者来说一点也不陌生,当然Qt也提供了一个元对象系统(The Meta-Object System),通过这个系统我们可以动态的在运行时获取一个类的构造函数、方法、字段、枚举等信息。但奇怪的是Qt文档中并没有提供类似于Java中Class.forName之类的方法,即类反射机制。经过网上查阅资料,发现大多数人实现此功能的方式都是自定义一个对象工厂(ObjectFactory)以模版的方式来实现的。后来我仔细阅读Qt文档,发现了Qt自带的类反射机制
     
    实现
    animal.h
    #ifndef ANIMAL_H
    #define ANIMAL_H
    
    #include <QObject>
    
    class Animal : public QObject
    {
        Q_OBJECT
    public:
        explicit Animal(QObject *parent = 0);
    
        virtual QString name() const = 0;
    };
    
    #endif // ANIMAL_H
    

    animal.cpp

    #include "animal.h"
    
    Animal::Animal(QObject *parent) : QObject(parent)
    {
    }
    

    person.h

    #ifndef PERSON_H
    #define PERSON_H
    
    #include "animal.h"
    
    class Person : public Animal
    {
        Q_OBJECT
    public:
        static int typeId;
    
        Q_INVOKABLE explicit Person(const QString &name, QObject *parent = 0);
        QString name() const;
    
    private:
        QString m_name;
    };
    
    #endif // PERSON_H
    

    person.cpp

    #include "person.h"
    
    int Person::typeId = qRegisterMetaType<Person*>();
    
    Person::Person(const QString &name, QObject *parent)
        : Animal(parent)
        , m_name(name)
    {
    }
    
    QString Person::name() const
    {
        return m_name;
    }
    

    main.cpp

    #include "animal.h"
    #include <QCoreApplication>
    #include <QDebug>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        int type = QMetaType::type("Person*");
        const QMetaObject *metaObj = QMetaType::metaObjectForType(type);
        QObject *obj = metaObj->newInstance(Q_ARG(QString, QStringLiteral("Rex")), Q_ARG(QObject*, nullptr));
        Animal *an = qobject_cast<Animal*>(obj);
        qDebug().noquote() << an->name();
        return a.exec();
    }
    
    Animal是一个虚基类,它有一个纯虚函数name,Person继承Animal并重写了name,一个非常简单的多态列子。可以看到在main.cpp中并没有包含Person类的头文件,仅仅通过"Person*"这个字符串就获得了Person类的元对象,并通过newInstance调用了Person的构造函数,最后通过qobject_cast把obj向下转型为Animal an,通过an调用虚函数name。
     
    需要注意的地方是:Person的构造函数必须声明为Q_INVOKABLE,否则newInstance无法调用该构造函数。另外必须要在main函数执行之前调用qRegisterMetaType<Person*>()注册Person,否则QMetaType::type无法获取Person*的类型ID。因为静态变量始终在main函数执行之前初始化,所以我通过在Person中增加了一个typeId的静态成员变量,在初始化的时候调用qRegisterMetaType<Person*>()来达到效果。

    https://blog.csdn.net/kenier/article/details/62041312 

  • 相关阅读:
    Python开发环境Spyder介绍
    Python干货整理之数据结构篇
    通过Python爬虫按关键词抓取相关的新闻
    疫情后来场说走就走的旅行,Python制作一份可视化的旅行攻略
    详细介绍去一年在 PyPI 上下载次数最多的 Python 包
    Python错误与异常
    python爬虫爬取2020年中国大学排名
    微信史上最短的一行功能代码:拍一拍
    Python爬取某宝商品数据案例:100页的价格、购买人数等数据
    我的SAS菜鸟之路7
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/4176421.html
Copyright © 2020-2023  润新知