Почему я получаю "undefined ссылку на vtable..." при связывании этого приложения Qt 5.0?

У меня есть относительно простой проект Qt 5.0, который использует CMake 2.8.9:

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
project(hello-world)

find_package(Qt5Widgets REQUIRED)
qt5_wrap_ui(hello-world_UI MainWindow.ui)

add_executable(hello-world MainWindow.cpp main.cpp ${hello-world_UI})
qt5_use_modules(hello-world Widgets)

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

    public:

        MainWindow();
        virtual ~MainWindow();

    private:

        Ui::MainWindow * const ui;
};

#endif // CMAINWINDOW_H

mainwindow.cpp:

#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow()
    : ui(new Ui::MainWindow)
{
}

MainWindow::~MainWindow()
{
    delete ui;
}

main.cpp:

#include <QApplication>
#include "MainWindow.h"

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);

    MainWindow win;
    win.show();

    return app.exec();
}

В проект также входит файл .ui, созданный с помощью Qt Creator 2.6.1 (MainWindow.ui).

Когда я пытаюсь создать файл с g++ в Linux, я получаю следующие ошибки:

CMakeFiles/hello-world.dir/MainWindow.cpp.o: In function `MainWindow::MainWindow()':
MainWindow.cpp:(.text+0x3b): undefined reference to `vtable for MainWindow'
MainWindow.cpp:(.text+0x4d): undefined reference to `vtable for MainWindow'
CMakeFiles/hello-world.dir/MainWindow.cpp.o: In function `MainWindow::~MainWindow()':
MainWindow.cpp:(.text+0xaf): undefined reference to `vtable for MainWindow'
MainWindow.cpp:(.text+0xc1): undefined reference to `vtable for MainWindow'
collect2: error: ld returned 1 exit status

Что может быть причиной такого рода ошибок? Недавно я переключился на CMake с qmake, и я никогда не задумываюсь о том, чтобы справиться с этой проблемой, получив тривиальный пример для компиляции. Что я делаю неправильно?


Изменить: здесь используется команда, которая связывает все:

/usr/bin/c++ CMakeFiles/hello-world.dir/MainWindow.cpp.o
CMakeFiles/hello-world.dir/main.cpp.o -o hello-world -rdynamic
/usr/local/Qt-5.0.0/lib/libQt5Widgets.so.5.0.0
/usr/local/Qt-5.0.0/lib/libQt5Gui.so.5.0.0
/usr/local/Qt-5.0.0/lib/libQt5Core.so.5.0.0 
-Wl,-rpath,/usr/local/Qt-5.0.0/lib

Ответы

Ответ 1

Оказывается, я забыл:

set(CMAKE_AUTOMOC ON)

В верхней части файла CMakeLists.txt.

Ответ 2

Я долго боролся с этим, используя все намеки, опубликованные здесь:

http://doc.qt.io/qt-5/cmake-manual.html

И здесь

https://www.kdab.com/using-cmake-with-qt-5/

Мне нужно было указать вещи в правильном порядке. Например, следующая вершина моего CMakeLists.txt. Обратите внимание, что две директивы set CMAKE относятся к add_executable. Как только я это сделал, мне удалось связать без undefined символов и ссылок на vtable. Я просто подумал, что опубликую это на благо других.

cmake_minimum_required (VERSION 2.8)

set (CMAKE_AUTOMOC ON)
set (CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(FHSpectrumSensor wideband_seq_spectrum_sensor.cpp sensor.cpp   gui.cpp ${gui_SRC})

Позже в CMakeLists.txt у меня есть следующее:

 find_package(Qt5Widgets REQUIRED)
 find_package(Qt5Charts REQUIRED)
 find_package(Qt5Core REQUIRED)

 qt5_use_modules(FHSpectrumSensor Widgets Charts)
 qt5_wrap_cpp(gui_SRC gui.h gui.cpp)

Это сделал трюк.

Ответ 3

Я также столкнулся с этой проблемой вчера, и вышеупомянутые ответы не помогли. Я уже использовал set (CMAKE_AUTOMOC ON), а также qt5_wrap_cpp.

Я пытался вспомнить, что я сделал, потому что у меня была рабочая версия, но она перестала работать после "некоторых" изменений. В конце концов я вспомнил, что пытался разделить включаемые файлы в отдельной иерархии каталогов. После возвращения этого и помещения включаемых файлов обратно в CMakeLists.txt он снова заработал. Я точно не знаю, почему, и я хотел бы знать, что пошло не так, но я решил сейчас оставить эти включения рядом с файлами cpp.

set(SOURCES
    buffer.h
    ITVSet.h
    MainWindow.h
    MainWindow.cpp
    TVSet.h
    TVSet.cpp
)