4

我知道我可以用它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_METATYPE并被Q_OBJECT应用。

4

2 回答 2

6

首先,要将参数传递给方法,您需要某种超越普通 C++ 的反射框架。使用 Qt,显而易见的选择是带有它的 Qt 元对象系统QMetaObject,但是您必须为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

QMetaTypedoc 说:“任何具有公共默认构造函数、公共复制构造函数和公共析构函数的类或结构都可以注册。” 这排除了 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,那么您需要提出一些您自己的类似(可能更轻且没有单独的编译器步骤)机制。

于 2013-10-21T20:04:43.877 回答
0

我有同样的问题。解决方案分为两步:

  1. 使用指针类型调用 qRegisterMetaType() :qRegisterMetaType< MyClass* >()。这会给你一个有效的 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
}
于 2014-01-18T10:14:11.873 回答