Dynamic object creation in Qt6
-
I want to create object of a class which inherited from QObject. The my following code work excelent in Qt5.
int typeID = QMetaType::type(QString(deviceObject->type + "Device*").toLatin1()); if (typeID != QMetaType::UnknownType) { const QMetaObject *mo = QMetaType::metaObjectForType(typeID); if (mo) { QObject *objectPtr = mo->newInstance(Q_ARG(QObject*, nullptr)); device = static_cast<AbstractDevice*>(objectPtr); } }
I try to migrate the above to Qt6 and prepared the following
QMetaType metaType = QMetaType::fromName(QString(deviceObject->type + "Device*").toLatin1()); if (metaType.isValid() && metaType.flags().testFlag(QMetaType::PointerToQObject)) { void *instance = metaType.create(); device = static_cast<AbstractDevice*>(instance); }
Of course, I do registration
Q_DECLARE_METATYPE(TestDevice*); qRegisterMetaType<TestDevice*>("TestDevice*");
But looks a creation is wrong, as object is not valid. And I see on debuger is not enter into object's constructor.
Please help me adapt my code to Qt6
-
Not looked into the details but why do you now need QMetaType::create() instead QMetaObject::newInstance()?
-
Not looked into the details but why do you now need QMetaType::create() instead QMetaObject::newInstance()?
@Christian-Ehrlicher
Because newInstance is marked as depricated -
-
-
That method was just replaced with a variadic. It's an implementation detail, once the deprecated function gets removed the new version of the method steps in seamlessly so you don't need to worry about it. The compiler gives warning because a non-template method is always preferred to a template one.
You can trynewInstance<QObject*>(nullptr);
to force the template method to be used -
That method was just replaced with a variadic. It's an implementation detail, once the deprecated function gets removed the new version of the method steps in seamlessly so you don't need to worry about it. The compiler gives warning because a non-template method is always preferred to a template one.
You can trynewInstance<QObject*>(nullptr);
to force the template method to be used -
I re-coded, but in my case newInstance returns nullptr
QMetaType metaType = QMetaType::fromName(QString("TestDevice*").toLatin1().constData()); if (metaType.isValid() && metaType.flags().testFlag(QMetaType::PointerToQObject)) { const QMetaObject *mo = metaType.metaObject(); // Not sure about it - is that correct? if (mo) { QObject *objectPtr = mo->newInstance<TestDevice*>(nullptr); // Returns nullptr auto device = static_cast<TestDevice*>(objectPtr); device->setObjectName("ttt"); } }
-
QObject *objectPtr = mo->newInstance<TestDevice*>(nullptr); // Returns nullptr
The template argument(s) should be the type of the argument(s) of the constructor.
if the constructor isTestDevice(QObject *parent)
then the template should bemo->newInstance<QObject*>(nullptr);
-
QObject *objectPtr = mo->newInstance<TestDevice*>(nullptr); // Returns nullptr
The template argument(s) should be the type of the argument(s) of the constructor.
if the constructor isTestDevice(QObject *parent)
then the template should bemo->newInstance<QObject*>(nullptr);
-
Just to make it clearer, imagine
newInstance
is:template <class T> QObject* newInstance(T arg){ return new TestDevice(arg); }
In your code you are calling
newInstance<TestDevice*>
soT
isTestDevice*
. SinceTestDevice
doesn't have a constructorTestDevice(TestDevice*)
the compiler fails.T
should be aQObject*
because that's what theTestDevice
constructor expects so the template argument should beQObject*
-
Just to make it clearer, imagine
newInstance
is:template <class T> QObject* newInstance(T arg){ return new TestDevice(arg); }
In your code you are calling
newInstance<TestDevice*>
soT
isTestDevice*
. SinceTestDevice
doesn't have a constructorTestDevice(TestDevice*)
the compiler fails.T
should be aQObject*
because that's what theTestDevice
constructor expects so the template argument should beQObject*
@VRonin Many thanks! Now all works as should be. Latest version is
QMetaType metaType = QMetaType::fromName("TestDevice*"); if (metaType.isValid() && metaType.flags().testFlag(QMetaType::PointerToQObject)) { const QMetaObject* metaObject = metaType.metaObject(); if (metaObject) { // Correctly use the type TestDevice* with newInstance QObject* objectPtr = metaObject->newInstance<QObject*>(nullptr); // Pass nullptr for the parent argument if (objectPtr) { auto device = static_cast<TestDevice*>(objectPtr); device->setObjectName("ttt"); qDebug() << "Device created and object name set to:" << device->objectName() << device->metaObject()->className(); } else { qWarning() << "Failed to create an instance using newInstance for type: TestDevice*"; } } else { qWarning() << "MetaObject is null for type: TestDevice*"; } } else { qWarning() << "Invalid or unsupported type: TestDevice*"; }
-