Ничто не помогло решить «Неопределенную ссылку на vtable» в Qt

#c #qt #qobject

#qt #vtable #qobject

Вопрос:

Я не могу создать это с ошибкой «неопределенная ссылка на vtable для CustomUndoStack»

Вот код:

 class CustomUndoStack : public QObject
{
    Q_OBJECT

public:

};


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

    CustomUndoStack uStack;

    return qCoreApplication.exec();
}
  

Вот файл .pro:

 QT  = widgets

CONFIG  = c  14 console
CONFIG -= app_bundle

DEFINES  = QT_DEPRECATED_WARNINGS

SOURCES  = main.cpp
  

Я вручную удалил каталог сборки, я пробовал «Очистить все» и «Перестроить все» всеми возможными способами, я запускал qmake 100500 раз, я менял пользовательский интерфейс poststack более 9000 раз, но ничего не помогает.

В чем проблема?

UPD, чтобы ответить на комментарий: если я удалю строку Q_OBJECT, я не смогу этого сделать. В нем говорится, что «Нет такого сигнала QObject::undoSignal()»

 class CustomUndoStack : public QObject
{
//    Q_OBJECT

public:
    CustomUndoStack() {
        connect(this, SIGNAL(undo_signal()), amp;undoStack, SLOT(undo()));
    }
signals:
    void undo_signal();
private:
    QUndoStack undoStack;
};
  

Комментарии:

1. Кстати, я использую Qt 5.9

Ответ №1:

Ваша проблема вызвана тем фактом, что у вас есть объявление подкласса класса QObject и наличие Q_OBJECT макроса внутри него в .cpp файле; Этот макрос содержит, среди прочего, объявление виртуального метода:

 virtual const QMetaObject *metaObject() const;
  

qmake инструмент обрабатывает только файлы заголовков, чтобы найти QObject подклассы, содержащие Q_OBJECT макрос, для автоматической генерации фактического кода, соответствующего объявлениям, созданным Q_OBJECT макросом. В вашем случае qmake не обрабатывает main.cpp файл и, следовательно, он остается содержащим нереализованную виртуальную функцию — отсюда и ошибка компоновщика, которую вы получаете.

Правильное решение — переместить объявление класса в отдельный файл заголовка и добавить заголовок в ваш проект. Есть, однако, другое решение, которое является своего рода хакерским, но его можно использовать, если вам по какой-то причине абсолютно необходимо оставить объявление вашего класса внутри .cpp файла:

 class CustomUndoStack : public QObject
{
    Q_OBJECT
public:
    CustomUndoStack(QObject * parent = 0) : QObject(parent) {}
};

#include "main.moc"

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

    CustomUndoStack uStack;

    return qCoreApplication.exec();
}
  

Обратите внимание на #include "main.moc" линию. Наличие этой строки заставляет qmake фактически обрабатывать объявления из вашего .cpp файла и генерировать требуемый .moc файл, который содержит автоматически сгенерированный код, соответствующий объявлениям, созданным Q_OBJECT макрокомандой.