Неопределенная ссылка на vtable... макрос Q_OBJECT

Когда я раскомментирую макрос Q_OBJECT, который мне нужен для сигнального слота, я получаю неопределенную ссылку на vtable для ошибки MyApp, но без макроса он компилируется отлично, но я не могу использовать сигналы и слоты без него. Я думаю, что я могу делать что-то глупое неправильно, но, пожалуйста, попробуйте помочь, потому что я действительно не могу найти проблему. О, и я знаю, что мой код неопрятен, и я работаю над этим.

myapp.h:

#ifndef MYAPP_H
#define MYAPP_H

#include <QApplication>
#include <QEvent>
#include <QObject>
#include <QDebug>

class MyApp : public QApplication
{

public:
    MyApp( int argc, char** argv );

protected:
    bool eventFilter(QObject *object, QEvent *event);

signals:
    void focusG();
    void focusL();
};

#endif // MYAPP_H

myapp.cpp:

#include "myapp.h"

MyApp::MyApp(int argc, char **argv): QApplication(argc, argv)
{
    installEventFilter(this);
}

bool MyApp::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::ApplicationDeactivate)
    {
        qDebug() << "Focus lost";
        //focusL();
    }
    if (event->type() == QEvent::ApplicationActivate)
    {
        qDebug() << "Focus gained";
        //focusG();
    }

    return false;
}

main.cpp:

#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QObject>
#include <QGraphicsObject>
#include <QTimer>
#include <QVariant>
#include "timecontrol.h"
#include "scorecontrol.h"
#include "Retry.h"
#include <QEvent>
#include "myapp.h"

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

    QmlApplicationViewer viewer;
    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationLockLandscape);
    viewer.setMainQmlFile(QLatin1String("qml/Raker/main.qml"));
    viewer.showExpanded();

    QObject *rootObject = viewer.rootObject();

    QTimer *timmer = new QTimer;
    timmer->setInterval(1000);

    TimeControl *timcon = new TimeControl;

    scorecontrol *scorer = new scorecontrol;

    Retry *probeer = new Retry;

    QObject::connect(timmer, SIGNAL(timeout()), timcon, SLOT(updateTime()));
    QObject::connect(timcon, SIGNAL(setTime(QVariant)), rootObject, SLOT(setTime(QVariant)));
    QObject::connect(rootObject, SIGNAL(blockClicked(int, int)), scorer, SLOT(checkRight(int, int)));
    QObject::connect(scorer, SIGNAL(setScore(QVariant)), rootObject, SLOT(setScore(QVariant)));
    QObject::connect(scorer, SIGNAL(setState(QVariant)), rootObject, SLOT(setState(QVariant)));

    QObject::connect(rootObject, SIGNAL(start()), probeer, SLOT(Reetry()));
    QObject::connect(probeer, SIGNAL(start()), timmer, SLOT(start()));
    QObject::connect(probeer, SIGNAL(stop()), timmer, SLOT(stop()));
    QObject::connect(probeer, SIGNAL(start(int)), scorer, SLOT(randomNum(int)));
    QObject::connect(probeer, SIGNAL(sReset()), timcon, SLOT(reset()));
    QObject::connect(probeer, SIGNAL(tReset()), scorer, SLOT(reset()));
    QObject::connect(timcon, SIGNAL(timeOut()), scorer, SLOT(reset()));

    QObject::connect(timcon, SIGNAL(setState(QVariant)), rootObject, SLOT(setState(QVariant)));
    QObject::connect(timcon, SIGNAL(changeFinal()), scorer, SLOT(changeFinal()));
    QObject::connect(scorer, SIGNAL(setFinal(QVariant)), rootObject, SLOT(setFinal(QVariant)));

    QObject::connect(&app, SIGNAL(focusL()), probeer, SLOT(focusL()));
    QObject::connect(&app, SIGNAL(focusG()), probeer, SLOT(focusG()));

    return app.exec();
}

BlockToucher.pro:

# Add more folders to ship with the application, here
folder_01.source = qml/Raker
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01

# Additional import path used to resolve QML modules in Creator's code model
QML_IMPORT_PATH =

symbian:TARGET.UID3 = 0x2004b49f

# Smart Installer package's UID
# This UID is from the protected range and therefore the package will
# fail to install if self-signed. By default qmake uses the unprotected
# range value if unprotected UID is defined for the application and
# 0x2002CCCF value if protected UID is given to the application
symbian:DEPLOYMENT.installer_header = 0x2002CCCF

# Allow network access on Symbian
symbian {
    #TARGET.CAPABILITY += NetworkServices

    vendorinfo = "%{\"Gerhard de Clercq\"}" ":\"Gerhard de Clercq\""
    ICON = BlockToucher.svg
}

# If your application uses the Qt Mobility libraries, uncomment the following
# lines and add the respective components to the MOBILITY variable.
# CONFIG += mobility
# MOBILITY +=

# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp \
    timecontrol.cpp \
    scorecontrol.cpp \
    Retry.cpp \
    myapp.cpp \
    myapplication.cpp

# Please do not modify the following two lines. Required for deployment.
include(qmlapplicationviewer/qmlapplicationviewer.pri)
qtcAddDeployment()

HEADERS += \
    timecontrol.h \
    scorecontrol.h \
    Retry.h \
    myapp.h \
    myapplication.h

OTHER_FILES += \
    qtc_packaging/debian_fremantle/rules \
    qtc_packaging/debian_fremantle/README \
    qtc_packaging/debian_fremantle/copyright \
    qtc_packaging/debian_fremantle/control \
    qtc_packaging/debian_fremantle/compat \
    qtc_packaging/debian_fremantle/changelog
compat \
    qtc_packaging/debian_fremantle/changelog

2 ответа

Q_OBJECT используется системой MOC для создания кода, необходимого для сигналов. Моим лучшим предположением будет то, что вы не включили сгенерированные файлы MOC в ваш проект (файлы CPP, которые он генерирует).

То, как вы это сделаете, во многом зависит от вашей системы сборки (CMake, QMake, AUtomake, MSVC), но вы должны сначала обратиться к руководству по QMake.

То есть неопределенная ссылка на vtable - это ошибка, которую я иногда получаю, когда забываю обновить мои файлы Cmake и получить Q_OBJECT.

Кроме того, ваш ctor для MyApp неверен, подпись должна быть:

MyApp( int & argc, char** argv );

& Это важно, если вы когда-либо используете параметры командной строки.

У меня была такая же проблема, когда я решил добавить Q_OBJECT в мой заголовочный файл.
Супер простое решение это:

  1. Добавить новый временный класс с QObject в качестве базового класса
  2. Дважды проверьте заголовок и исходный файл на наличие ошибок, используя новый временный класс
  3. Создайте свой проект. Должно быть успешно построено
  4. Полностью удалите временный класс (файл.h и.cpp и соответствующие строки в файле.pro)

Наслаждаться:)

Другие вопросы по тегам