I know that I can use QMetaType
to create an object without parameters.
Another possible option is to use QMetaObject
and call newInstance
. But I need to get QMetaObject
from something.
I tried to use QMetaType::metaObjectForType
, but it always returns null pointer (but QMetaType
is able to create the object).
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
UPDATE:
I think the question is why metaObjectForType
does not work for me.
The class is registered with qRegisterMetaType
, also Q_DECLARE_METATYPE
and Q_OBJECT
are applied.
First of all, to pass parameters to methods, you needs some kind of reflection framework beyond plain C++. With Qt, the obivous choice is Qt Meta Object system with it's QMetaObject
, though then you must derive your classes for QObject
. After that, you need to do two things:
Signals and slots are invokable by default, but any other method you want to invoke through the meta object system needs to be explicitly marked as such. Example 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
QMetaObject
QMetaType
doc says: "any class or struct that has a public default constructor, a public copy constructor, and a public destructor can be registered." This rules out QObject, because they can't have copy constructors. You need to create your own mapping from name to the meta object. An example shown in this 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;
}
If you do not want to use QObject
, then you need to come up with some similar (probably lighter-weight and without separate compiler step) mechanism of your own.