How do you append an object to QList?

waspinator picture waspinator · Aug 12, 2014 · Viewed 20k times · Source

I'm trying to create a list of objects using QList, but I'm getting an error when I try to add to the list. It works if I use QString as the object, but not if I use TestClass.

updated main.cpp that works. is this the correct way of doing things?

#include <QCoreApplication>
#include <QDebug>

#include "testclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QList<TestClass*> test_list;

    TestClass* test_1 = new TestClass;
    test_1->test_varialbe = 1;
    test_list.append(test_1);

    TestClass* test_2 = new TestClass;
    test_2->test_varialbe = 2;
    test_list.append(test_2);

    foreach(TestClass* t, test_list) {
        qWarning() << t->test_varialbe;
    }

    return a.exec();
}

main.cpp

#include <QCoreApplication>

#include "testclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QList<TestClass> test_list;
    TestClass test;
    test_list.append(test);

    return a.exec();
}

testclass.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include <QObject>

class TestClass : public QObject
{
    Q_OBJECT
public:
    explicit TestClass(QObject *parent = 0);
    int test_varialbe;

signals:

public slots:

};

#endif // TESTCLASS_H

testclass.cpp

#include "testclass.h"

TestClass::TestClass(QObject *parent) :
    QObject(parent)
{
}

error

In file included from ../poo/main.cpp:3:
../poo/testclass.h:6:7: error: base class 'QObject' has private copy constructor
class TestClass : public QObject
      ^
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qlist.h:691:9: note: in instantiation of member function 'QList<TestClass>::node_copy' requested here
        node_copy(reinterpret_cast<Node *>(p.begin()),
        ^
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qlist.h:520:19: note: in instantiation of member function 'QList<TestClass>::detach_helper_grow' requested here
        Node *n = detach_helper_grow(INT_MAX, 1);
                  ^
../poo/main.cpp:11:15: note: in instantiation of member function 'QList<TestClass>::append' requested here
    test_list.append(test);
              ^
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qobject.h:465:20: note: declared private here
    Q_DISABLE_COPY(QObject)
                   ^
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qglobal.h:1000:5: note: expanded from macro 'Q_DISABLE_COPY'
    Class(const Class &) Q_DECL_EQ_DELETE;\
    ^
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qlist.h:400:34: note: implicit copy constructor for 'TestClass' first required here
                current->v = new T(*reinterpret_cast<T*>(src->v));
                                 ^
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qlist.h:413:31: error: no matching constructor for initialization of 'TestClass'
                new (current) T(*reinterpret_cast<T*>(src));
                              ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
../poo/testclass.h:10:14: note: candidate constructor not viable: no known conversion from 'TestClass' to 'QObject *' for 1st argument; remove *
    explicit TestClass(QObject *parent = 0);
             ^
In file included from ../poo/main.cpp:1:
In file included from ../Qt/5.3/clang_64/lib/QtCore.framework/Versions/5/Headers/QCoreApplication:1:
In file included from ../Qt/5.3/clang_64/lib/QtCore.framework/Versions/5/Headers/qcoreapplication.h:48:
In file included from /Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qobject.h:51:
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qlist.h:373:69: error: no matching constructor for initialization of 'TestClass'
    if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
                                                                    ^ ~
/Users/waspinator/Qt/5.3/clang_64/lib/QtCore.framework/Headers/qlist.h:522:13: note: in instantiation of member function 'QList<TestClass>::node_construct' requested here
            node_construct(n, t);
            ^
../poo/main.cpp:11:15: note: in instantiation of member function 'QList<TestClass>::append' requested here
    test_list.append(test);
              ^
../poo/testclass.h:10:14: note: candidate constructor not viable: no known conversion from 'const TestClass' to 'QObject *' for 1st argument
    explicit TestClass(QObject *parent = 0);
             ^
3 errors generated.
make: *** [main.o] Error 1
14:37:52: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project poo (kit: Desktop Qt 5.3.0 clang 64bit)
When executing step 'Make'

Answer

RA. picture RA. · Aug 12, 2014

From the documentation for QList:

QList's value type must be an assignable data type. This covers most data types that are commonly used, but the compiler won't let you, for example, store a QWidget as a value; instead, store a QWidget *.

Also refer to the documentation on Qt's Container Classes .

In summary, you must use a pointer to a QObject if you wish to use it with a QList:

QList<TestClass*> test_list;

Note that this means that you are responsible for ensuring that the QObject has not been deleted if your code is still using the QList.


Update: Again, you are responsible for managing the life cycle of the QObject inserted into the list. There are several ways to do this. You could instantiate the TestClass on the heap, but you should ensure that the object gets deleted when the application exits. One way to do this is to give the TestClass a parent object:

QCoreApplication a(argc, argv);

QList<TestClass*> test_list;

TestClass* test_1 = new TestClass(&a);
test_list.append(test_1);

You could also avoid creating the TestClass on the heap altogether, though it will be automatically destroyed when the function it is created in goes out of scope:

QList<TestClass*> test_list;
TestClass test_1;
test_list.append(&test_1);

I strongly recommend researching memory management in C++, as well as the role of the stack and the heap (and when to use each). It's too broad to cover here.