I need to make multiple instances of various class types (classA, classB, classC), and store then in a single list. Is is possible to create these objects dynamically and then add them to a single QList? Something like:
QList<QObject> mylist;
mylist.append(classA());
mylist.append(classB());
mylist.append(classC());
This won't compile because the objects are not of type QObject. I could static_cast them to QObject, but will I be able to typeid.name() to determine their origical types? (To cast them back later)?
I found an example here of using a QList< QVariant >, but the compiler complains that:
error: no matching function for call to 'QVariant::QVariant(classA&)'
for this code:
QList<QVariant> mylist;
mylist.append(QVariant(tempObj));
Update:
I got it compiling by creating the object during the append operation, AND using ::fromValue.
mylist.append(QVariant::fromValue(ClassA(1,2,3)));
Not sure this is right. 1 - will this cause a memory leak/problem creating the object in the append statement? 2 - why would I need ::fromValue to make this work? (Does this just make a second copy of the object?)
I put a qDebug in my constructors, and I see that my constructor with parameters is called twice, then the copy constructor is called once, and the default (no parameters) constructor is never called. I don't understand that...
You can use QVariant
which can hold any number of different types: QVariant API
To use QVariant
with a custom type you need to register it with the metatype system: QMetaType This means using Q_DECLARE_METATYPE(MyClass)
Q_DECLARE_METATYPE()
QVariant is designed for holding objects of different types, and is used in all sorts of Qt conventions when the programmer wants to pass around user-defined types through Qt's interfaces when Qt itself has no way of knowing which type the programmer wants to use.
To convert back to the original type use a combination of QVariant::canConvert()
and QVariant::value()
:
QVariant v;
MyCustomStruct c;
if (v.canConvert<MyCustomStruct>())
c = v.value<MyCustomStruct>();
v = 7;
int i = v.value<int>(); // same as v.toInt()
QString s = v.value<QString>(); // same as v.toString(), s is now "7"
MyCustomStruct c2 = v.value<MyCustomStruct>(); // conversion failed, c2 is empty
Your custom type must provide:
The following Message
class is an example of an acceptable custom type for use in QVariant
class Message
{
public:
Message();
Message(const Message &other);
~Message();
Message(const QString &body, const QStringList &headers);
QString body() const;
QStringList headers() const;
private:
QString m_body;
QStringList m_headers;
};
You could also declare your own "meta-type wrapper" that holds a type and a description of a type. The simplest example:
template <typename T>
class AnyType
{
public:
enum THE_TYPE { MT_INT, MT_STRING };
AnyType(T value, THE_TYPE type) : value(value), type(type) { }
THE_TYPE getType() { return type; }
T getValue() { return value; }
private:
T value;
THE_TYPE type;
}