'Qt C++ : Cannot instantiate class derived from QAbstractListModel

Using Qt wizzard I created ToDoListModel2 class derived from QAbstractListModel. Code:

todolistmodel2.h

#ifndef TODOLISTMODEL2_H
#define TODOLISTMODEL2_H

#include <QAbstractListModel>

class ToDoListModel2 : public QAbstractListModel
{
    Q_OBJECT

public:
    explicit ToDoListModel2(QObject *parent = nullptr);

    // Header:
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

    bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;

    // Basic functionality:
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    // Editable:
    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole) override;

    Qt::ItemFlags flags(const QModelIndex& index) const override;

    // Add data:
    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;

    // Remove data:
    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;

private:
};

#endif // TODOLISTMODEL2_H

todolistmodel2.cpp

#include "todolistmodel2.h"

ToDoListModel2::ToDoListModel2(QObject *parent)
    : QAbstractListModel(parent)
{
}

QVariant ToDoListModel2::headerData(int section, Qt::Orientation orientation, int role) const
{
    // FIXME: Implement me!
    return QVariant();
}

bool ToDoListModel2::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
{
    if (value != headerData(section, orientation, role)) {
        // FIXME: Implement me!
        emit headerDataChanged(orientation, section, section);
        return true;
    }
    return false;
}

int ToDoListModel2::rowCount(const QModelIndex &parent) const
{
    // For list models only the root node (an invalid parent) should return the list's size. For all
    // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
    if (parent.isValid())
        return 0;

    // FIXME: Implement me!
    return 0;
}

QVariant ToDoListModel2::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    // FIXME: Implement me!
    return QVariant();
}

bool ToDoListModel2::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (data(index, role) != value) {
        // FIXME: Implement me!
        emit dataChanged(index, index, {role});
        return true;
    }
    return false;
}

Qt::ItemFlags ToDoListModel2::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; // FIXME: Implement me!
}

bool ToDoListModel2::insertRows(int row, int count, const QModelIndex &parent)
{
    beginInsertRows(parent, row, row + count - 1);
    // FIXME: Implement me!
    endInsertRows();
    return true;
}

bool ToDoListModel2::removeRows(int row, int count, const QModelIndex &parent)
{
    beginRemoveRows(parent, row, row + count - 1);
    // FIXME: Implement me!
    endRemoveRows();
    return true;
}

I just want to instantiate ToDoListModel2 like this:

ToDoListModel2* model = new ToDoListModel2();

When i put this line in main.cpp it works fine:

#include "mainwindow.h"
#include "todolistdata.h"
#include <QApplication>
#include <QTest>
#include "todolistmodel2.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qRegisterMetaType<ToDoListData>();
    ToDoListModel2* model = new ToDoListModel2();
    MainWindow w;
    w.setWindowState(Qt::WindowMaximized);
    w.show();
    return a.exec();
}

But when I put this line in method of other class:

#include "timer.h"
#include "ui_timer.h"
#include <QTimer>
#include "windows.h"
#include <QMediaPlayer>
#include <QAudioOutput>
#include <QMediaDevices>
#include <QAudioDevice>
#include <QFile>
#include "filepath.h"
#include "todolistmodel2.h"
Timer::Timer(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Timer)
{
    ToDoListModel2* model = new ToDoListModel2();
}

I get a compile error:

timer.cpp:16: error: undefined reference to 'ToDoListModel2::ToDoListModel2(QObject*)'

So how I can overcome this ?

I tried to move defenition of constructor to header, previous error is replaced with this: undefined reference to vtable

Then I tried do add virtual destructor virtual ~ToDoListModel2() {}; but it didn't help.

header and cpp included in .pro file :

QT       += core gui
QT       += multimedia
QT       += core testlib
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    addnewprojectdialog.cpp \
    addtotodolist.cpp \
    filepath.cpp \
    main.cpp \
    mainwindow.cpp \
    settingsdialog.cpp \
    timer.cpp \
    todolistdata.cpp \
    todolistmodel.cpp \
    todolistmodel2.cpp \
    todolistwindow.cpp

HEADERS += \
    addnewprojectdialog.h \
    addtotodolist.h \
    filepath.h \
    mainwindow.h \
    settingsdialog.h \
    timer.h \
    todolistdata.h \
    todolistmodel.h \
    todolistmodel2.h \
    todolistwindow.h

FORMS += \
    addnewprojectdialog.ui \
    addtotodolist.ui \
    mainwindow.ui \
    settingsdialog.ui \
    timer.ui \
    todolistwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    Resources.qrc

Please, help!

// UPD: Tried to Clean, Run qmake, Build, Rebuild, reboot Qt. Didn't help.

// UPD2: Everything works in brand new project.



Solution 1:[1]

Solution: the problem was that I didn't add todolistmodel.h and .cpp to other project that was in subdirs project. When I did, everything started working.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Oleksii