Qt Meta System调用带参数的构造函数

时间:2013-10-21 19:59:27

标签: qt qtcore

我知道我可以使用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已应用。

2 个答案:

答案 0 :(得分:5)

首先,要将参数传递给方法,除了普通的C ++之外,还需要某种反射框架。对于Qt,一个明显的选择是Qt元对象系统,它是QMetaObject,但是你必须为QObject派生你的类。之后,您需要做两件事:

1。 make构造函数可调用

默认情况下,信号和插槽是可调用的,但是您想要通过元对象系统调用的任何其他方法都需要明确标记。示例 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,那么您需要提出自己的一些类似(可能更轻,没有单独的编译器步骤)机制。

答案 1 :(得分:0)

我遇到了同样的问题。 解决方案分为两个步骤:

  1. 使用指针类型调用qRegisterMetaType(): qRegisterMetaType&LT;的 MyClass的* &GT;()。这会给你一个有效的 调用QMetaType :: metaObjectForType(id)的QMetaObject;
  2. 使你的构造函数Q_INVOKABLE。这将启用有效的呼叫 QMetaObject ::的newInstance
  3. 还要确保您的类派生自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
    }