Qt的类反射机制


版权声明:本文为CSDN博主「astro_lee」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kenier/article/details/62041312

前言

如何通过类名动态的创建对象(类反射),对于Java开发者来说一点也不陌生,当然Qt也提供了一个元对象系统(The Meta-Object System),通过这个系统我们可以动态的在运行时获取一个类的构造函数、方法、字段、枚举等信息。但奇怪的是Qt文档中并没有提供类似于Java中Class.forName之类的方法,即类反射机制。经过网上查阅资料,发现大多数人实现此功能的方式都是自定义一个对象工厂(ObjectFactory)以模版的方式来实现的。后来我仔细阅读Qt文档,发现了Qt自带的类反射机制

实现
 

//animal.h
  
 #include <QObject>
     
 class Animal : public QObject
{
     Q_OBJECT
 public:
     explicit Animal(QObject *parent = 0);
     
     virtual QString name() const = 0;
};
     

//animal.cpp

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

 

//person.h
   
#include "animal.h"
     
class Person : public Animal
 {
    Q_OBJECT
  public:
      static int typeId;
     
      //使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起。
      Q_INVOKABLE explicit Person(const QString &name, QObject *parent = 0);
      QString name() const;
   
   private:
      QString m_name;
};
     



//person.cpp

#include "person.h"

//如果要在Qt信号槽中使用自定义类型,需要注意使用qRegisterMetaType对自定义类型进行注册     
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*>()来达到效果。
 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值