【问题标题】:Qt Meta System Call constructor with parameters带参数的 Qt Meta System Call 构造函数
【发布时间】:2013-10-21 19:59:27
【问题描述】:

我知道我可以使用QMetaType 来创建一个不带参数的对象。

另一个可能的选择是使用QMetaObject 并调用newInstance。但我需要从某事中得到QMetaObject

我尝试使用QMetaType::metaObjectForType,但它总是返回空指针(但QMetaType 能够创建对象)。

QMetaObject const* metaObject = QMetaType::metaObjectForType(id); // return null pointer
   QObject*           object     =   (QObject*)QMetaType::create(id); // create the object
QMetaObject const* metaObject = object->metaObject(); // return not-null pointer

更新:

我认为问题是为什么metaObjectForType 对我不起作用。 该类注册了qRegisterMetaType,同时应用了Q_DECLARE_METATYPEQ_OBJECT

【问题讨论】:

    标签: qt qtcore


    【解决方案1】:

    首先,要将参数传递给方法,您需要某种超越普通 C++ 的反射框架。对于 Qt,显而易见的选择是带有 QMetaObject 的 Qt 元对象系统,但是您必须为 QObject 派生类。之后,你需要做两件事:

    1。使构造函数可调用

    默认情况下,信号和槽是可调用的,但是您想通过元对象系统调用的任何其他方法都需要明确标记为这样。示例 myqobject.h

    #ifndef MYQOBJECT_H
    #define MYQOBJECT_H
    #include <QObject>
    
    class MyQObject : public QObject
    {
        Q_OBJECT
    public:
        Q_INVOKABLE MyQObject(QObject *parent = 0); // tested with empty constructor in .cpp
    
    };
    
    #endif // MYQOBJECT_H
    

    2。创建您自己的从类名字符串到QMetaObject 的映射

    QMetaType doc 说:“任何具有公共默认构造函数、公共复制构造函数和公共析构函数的类或结构都可以注册。” 这排除了 QObject,因为它们可以'没有复制构造函数。您需要创建自己的从名称到元对象的映射。此 main.cpp 中显示的示例:

    #include <QCoreApplication>
    #include <QtCore>
    
    #include "myqobject.h"
    
    // a global map for mapping strings to QMetaObjects,
    // you need header file like this if you want to access it from other .cpp files:
    //
    // #include <QHash>
    // #include <QString>
    // class QMetaObject; // forward declaration, enough when only pointer is needed
    // extern QHash<QString, const QMetaObject*> metaObjs;
    //
    QHash<QString, const QMetaObject*> metaObjs;
    
    // optional: create a macro to avoid typing class name twice,
    // #c surrounds macro argument with double quotes converting it to string
    #define METAOBJS_INSERT(c) (metaObjs.insert(#c, &c::staticMetaObject))
    
    int main()
    {
        METAOBJS_INSERT(MyQObject);
    
        const QMetaObject *meta = metaObjs["MyQObject"];
        qDebug() << "Class name from staticMetaObject: " << meta->className();
    
        QObject *o = meta->newInstance(); // add constructor arguments as needed
        MyQObject *mo = qobject_cast<MyQObject*>(o);
        if (mo) qDebug() << "Class name from object instance: " << mo->metaObject()->className();
        else qDebug() << "Instance creation failed or created wrong class!";
    
        return 0;
    }
    

    如果你不想使用QObject,那么你需要自己想出一些类似的(可能更轻量级并且没有单独的编译器步骤)机制。

    【讨论】:

    • 这不是我想要的。当我尝试创建一个对象时,我真的没有它的类型。比如我想获取QWidget*,使用名称“MyWidget”来创建,不知道是MyWidget类。
    • 我告诉过“我尝试使用QMetaType::metaObjectForType,但它总是返回空指针(但QMetaType 能够创建对象)。”为什么会发生这种情况?
    • 是的,它适用于“QObject*”。请查看更新。
    • 这开始困扰我,所以我做了一些研究,并从头开始重写了答案(并删除了我早期的 cmets)。我认为这是您将使用 C++ 获得的最佳效果。我不知道,但是 boost 有各种很酷的东西,如果你不想使用 QObject 并且不想使用,它可能有一些反射功能可以用来代替 Qt推出自己的机制。
    【解决方案2】:

    我遇到了同样的问题。 解决方法分两步:

    1. 使用指针类型调用 qRegisterMetaType(): qRegisterMetaTypeMyClass*>()。这会给你一个有效的 QMetaObject 调用 QMetaType::metaObjectForType(id);
    2. 使您的构造函数为 Q_INVOKABLE。这将启用对 QMetaObject::newInstance

    还要确保你的类是从 QObject 派生的,并且里面有一个 Q_OBJECT 宏。

    class A : public QObject
    {
        Q_OBJECT
    public:
        A(const A&) {}; // dummy copy contructor that do nothing to disable error message
        Q_INVOKABLE A(int test_value = 99999) : TestValue(test_value) {};
        int TestValue;
    };
    Q_DECLARE_METATYPE(A);
    int main(int argc, char *argv[]) 
    {
        qRegisterMetaType<A>(); //you do not need this
        qRegisterMetaType<A*>();//the real registration
        int type_id_for_A = QMetaType::type("A"); // valid type id (in my case = 403)
        const QMetaObject *meta_object_for_A = QMetaType::metaObjectForType(type_id_for_A); // returns NULL
        int type_id_for_A_ptr = QMetaType::type("A*"); // valid type id (in my case = 404)
        const QMetaObject *meta_object_for_A_tr = QMetaType::metaObjectForType(type_id_for_A_ptr); // returns NOT NULL
        A* A_obj= dynamic_cast<A*>(meta_object_for_A_tr->newInstance(Q_ARG(int, 12345)));
        int test_value = A_obj->TestValue; // returns 12345, not 99999
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      • 1970-01-01
      • 2020-06-15
      • 2021-10-25
      • 2013-11-07
      相关资源
      最近更新 更多