对 vtable 的未定义引用... Q_OBJECT 宏

Ger*_*ddc 1 c++ macros qt undefined vtable

当我取消对信号槽所需的 Q_OBJECT 宏的注释时,我得到了一个对 vtable 的未定义引用,用于 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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

主.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();
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

edA*_*a-y 6

MOC 系统使用 Q_OBJECT 来生成信号所需的代码。我最好的猜测是你的项目中没有包含 MOC 生成的文件(它生成的 CPP 文件)。

您如何执行此操作在很大程度上取决于您的构建系统(CMake、QMake、AUtomake、MSVC),但您应该先参考 QMake 教程。

也就是说,当我忘记更新我的 Cmake 文件并有一个 Q_OBJECT 时,我有时会得到对 vtable 的未定义引用。

另外,你的 MyApp ctor 是错误的,签名必须是:

MyApp( int & argc, char** argv );
Run Code Online (Sandbox Code Playgroud)

&如果您使用命令行参数,这一点很重要。

  • @Gerhman 确实如此,但前提是 .pro 文件发生更改。如果非 mocable 文件变为 mocable(= 包含 `Q_OBJECT` 宏),则必须手动运行 qmake,以便更新 Makefile 以在它们上执行 moc。 (2认同)