4

QMetaTypeパラメータなしでオブジェクトを作成するために使用できることを知っています。

別の可能なオプションは、を使用QMetaObjectして呼び出すことnewInstanceです。しかし、私QMetaObjectは何かから取得する必要があります。

を使用しようとしましQMetaType::metaObjectForTypeたが、常に null ポインターを返します (ただし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問題は、なぜうまくいかないのかということだと思います。クラスは に登録されqRegisterMetaTypeQ_DECLARE_METATYPEおよびQ_OBJECTも適用されます。

4

2 に答える 2

6

まず第一に、パラメーターをメソッドに渡すには、単純な C++ を超えたある種のリフレクション フレームワークが必要です。Qt では、明らかな選択は Qt メタ オブジェクト システムでQMetaObjectあり、その場合は のクラスを派生させる必要がありますQObject。その後、次の 2 つのことを行う必要があります。

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

私も同じ問題を抱えていました。解決策は次の 2 つのステップです。

  1. ポインター型で qRegisterMetaType() を呼び出します: qRegisterMetaType< MyClass* >()。これにより、QMetaType::metaObjectForType(id); の呼び出しで有効な QMetaObject が得られます。
  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 に答える