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

发布于 2024-12-12 04:40:37 字数 5198 浏览 0 评论 0原文

当我取消注释信号槽所需的 Q_OBJECT 宏时,我得到了对 MyApp 错误的 vtable 的未定义引用,但是如果没有该宏,它可以完美编译,但如果没有它,我就无法使用信号和槽。我想我可能做错了一些愚蠢的错误,但请尝试帮助,因为我真的找不到问题。 O,我知道我的代码不整洁,正在处理它。

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

When I uncomment the Q_OBJECT macro that I need for signal-slot I get a undefined reference to vtable for MyApp error, but without the macro it compiles perfectly but I can't use signals and slots without it. I think I may be doing something stupid wrong, but please try helping because I realy can't find the problem. O and I know my code is untidy and am working on it.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白日梦 2024-12-19 04:40:37

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

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

也就是说,当我忘记更新 Cmake 文件并拥有 Q_OBJECT 时,有时会出现对 vtable 的未定义引用的错误。

另外,您的 MyApp 构造函数是错误的,签名必须是:

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

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

Q_OBJECT is used by the MOC system to produce the code you need for the signals. My best guess would be that you are not included the MOC generated files in your project (the CPP files which it generates).

How you do this greatly depends on your build system (CMake, QMake, AUtomake, MSVC) but you should refer to the tutorial with QMake first.

That is, the undefined reference to vtable is the error I sometimes get when I forget to update my Cmake files and have a Q_OBJECT.

Also, your ctor for MyApp is wrong, the signature must be:

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

The & is important should you ever use command-line parameters.

绻影浮沉 2024-12-19 04:40:37

当我决定将 Q_OBJECT 添加到我的头文件中时,我遇到了同样的问题。

  • 首先尝试手动运行qmake

  • 如果没有解决,请删除构建文件夹并重新构建项目

  • 如果构建所有项目是一项繁重的任务,请尝试以下步骤:

    1. 添加一个新的临时类,以 QObject 作为其基类
    2. 使用新的临时类仔细检查标头和源文件是否有任何错误
    3. 构建您的项目。它应该成功构建
    4. 完全删除临时类(.h 和 .cpp 文件以及 .pro 文件上的相关行)

祝你好运:)

I had same issue when i decided to add Q_OBJECT into my header file.

  • First try run qmake manually.

  • If not resolved, so delete build folder and build project again

  • If building all of the project is a heavy task, so try following steps:

    1. Add a new temp class with QObject as its base class
    2. Double check your header and source file for any mistake using new temp class
    3. Build your project. It should built successfully
    4. Remove your temp class completely (.h and .cpp file and relative lines on .pro file)

Good luck :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文