Qt C++:无法实例化从 QAbstractListModel 派生的 class
Qt C++ : Cannot instantiate class derived from QAbstractListModel
我使用 Qt wizzard 创建了从 QAbstractListModel 派生的 ToDoListModel2 class。代码:
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;
}
我只想像这样实例化 ToDoListModel2:
ToDoListModel2* model = new ToDoListModel2();
当我将此行放入 main.cpp 时,它工作正常:
#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();
}
但是当我把这一行放在其他方法中时 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();
}
我得到一个编译错误:
timer.cpp:16: error: undefined reference to 'ToDoListModel2::ToDoListModel2(QObject*)'
那么我该如何克服呢?
我试图将构造函数的定义移动到 header,之前的错误被替换为:
undefined reference to vtable
然后我尝试添加虚拟析构函数
virtual ~ToDoListModel2() {};
但它没有帮助。
header 和 .pro 文件中包含的 cpp :
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
求求你帮忙!
// UPD:尝试清理,运行 qmake,构建,重建,重启 Qt。没有帮助。
// UPD2:在全新的项目中一切正常。
解决方案:问题是我没有将 todolistmodel.h 和 .cpp 添加到子目录项目中的其他项目。当我这样做时,一切都开始工作了。
我使用 Qt wizzard 创建了从 QAbstractListModel 派生的 ToDoListModel2 class。代码:
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;
}
我只想像这样实例化 ToDoListModel2:
ToDoListModel2* model = new ToDoListModel2();
当我将此行放入 main.cpp 时,它工作正常:
#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();
}
但是当我把这一行放在其他方法中时 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();
}
我得到一个编译错误:
timer.cpp:16: error: undefined reference to 'ToDoListModel2::ToDoListModel2(QObject*)'
那么我该如何克服呢?
我试图将构造函数的定义移动到 header,之前的错误被替换为:
undefined reference to vtable
然后我尝试添加虚拟析构函数
virtual ~ToDoListModel2() {};
但它没有帮助。
header 和 .pro 文件中包含的 cpp :
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
求求你帮忙!
// UPD:尝试清理,运行 qmake,构建,重建,重启 Qt。没有帮助。
// UPD2:在全新的项目中一切正常。
解决方案:问题是我没有将 todolistmodel.h 和 .cpp 添加到子目录项目中的其他项目。当我这样做时,一切都开始工作了。