【问题标题】:Undefined reference to MasterController::StaticMetaObject对 MasterController::StaticMetaObject 的未定义引用
【发布时间】:2019-07-04 09:13:09
【问题描述】:

我刚刚开始学习 Qt,目前我正在阅读 Nicolas Sheriff 所著的Learn Qt 5一书。我在哪里,在第 2 章中,我正在遵循所有说明,并且我正在理解我在做什么,但我陷入了一件事情:当我与其他程序一起编译以下程序时,我得到了这个错误列表:image shwowing the error messages

这是project structure

我认为值得展示的文件是:

cm.pro 文件

QT       -= gui

TARGET = cm-lib
TEMPLATE = lib

CONFIG += c++17
DEFINES += CMLIB_LIBRARY
INCLUDEPATH += source

SOURCES += source/models/client.cpp \
           source/controllers/master-controller.cpp \

HEADERS += source/cm-lib_global.h \
           source/controllers/master-controller.h \
           source/models/client.h \

cm-lib.pro

QT       -= gui

TARGET = cm-lib
TEMPLATE = lib
CONFIG += c++17
DEFINES += CMLIB_LIBRARY
INCLUDEPATH += source

SOURCES += source/models/client.cpp \
           source/controllers/master-controller.cpp \

HEADERS += source/cm-lib_global.h \
           source/controllers/master-controller.h \
           source/models/client.h \

cm-ui.pro

QT += qml quick

TEMPLATE = app
CONFIG += c++17
INCLUDEPATH += source \
        ../cm-lib/source

SOURCES += source/main.cpp

RESOURCES += views.qrc
LIBS += -L$$PWD/../../build-cm-kit1-Debug/cm-lib/ -lcm-lib

MasterController.h

#ifndef MASTERCONTROLLER_H
#define MASTERCONTROLLER_H
#include <QObject>
#include <QString>
#include <cm-lib_global.h>

namespace cm::controllers {
class CMLIBSHARED_EXPORT MasterController : public QObject
{
    Q_OBJECT
    QString welcomeMessage = "This is MasterController to Major Tom";
    Q_PROPERTY( QString ui_welcomeMessage MEMBER welcomeMessage CONSTANT )
    public:
    explicit MasterController(QObject* parent = nullptr);
};
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <controllers/master-controller.h>

int main(int argc, char *argv[])
{
    #if defined(Q_OS_WIN)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif

    QGuiApplication app(argc, argv);

    qmlRegisterType<cm::controllers::MasterController>("CM", 1, 0, "MasterController");

    cm::controllers::MasterController masterController{};

    QQmlApplicationEngine engine{};
    engine.rootContext()->setContextProperty("masterController", &masterController);
    engine.load(QUrl(QStringLiteral("qrc:/views/MasterView.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

之所以长这样,是因为我在这里像书中一样使用了 MVC 设计模式。

我认为问题是由于在 MasterController.h 中包含 Q_OBJECT 宏引起的,因为当我删除它时,项目编译良好,没有任何问题。

在谷歌搜索该问题后,在我访问的几乎所有地方,错误是由于包含 Q_OBJECT 宏的类将在它们自己的头文件中声明或qmake 没有在这些文件上重新运行,包括 Q_OBJECT但在我的情况下不是这样。

使用的系统工具:

  • Qt 创建者
  • Qt 5.11 -Kubuntu 18.04

【问题讨论】:

  • .pro 文件的一个惊人替代品是.qbs 模型。在设置这些东西时,它更加冗长和直接。

标签: c++ qt


【解决方案1】:

未定义的引用很可能是由丢失的 moc 文件引起的。当子类化一个 qt 对象并使用 Q_OBJECT 宏时,Qt 元对象编译器会创建一个 moc 文件 (moc_master-controller.cpp),其中包含 qobject 相关定义,包括缺少的staticMetaObject。该源文件必须与类定义一起编译。这是在使用 qmake 时自动完成的。

根据您提供的代码,您的设置应该可以正常工作。有几件事可以尝试:

  • 再次运行 qmake。添加或删除 Q_OBJECT 宏后,必须再次运行 qmake。如果您在运行 qmake 之后添加 Q_OBJECT,则 makefile 不包含 master-controller.h 的 moc 命令。
  • 确保类从 lib 中正确导出,并且其他项目找到 lib 并正确导入。
  • 值得一试进行清理和重建,以防在之前的构建过程中出现问题。

我尝试根据您提供的代码重现该问题,但它对我来说编译得很好。如果您想与您的代码交叉引用,我在下面包含了我的代码。

cm-lib.pro

QT       -= gui

TARGET = cm-lib
TEMPLATE = lib
CONFIG += c++17
DEFINES += CMLIB_LIBRARY
INCLUDEPATH += source

SOURCES += master-controller.cpp

HEADERS += cm-lib_global.h \
    master-controller.h

cm-lib_global.h

#pragma once

#include <QtCore/QtGlobal>

#if defined(CMLIB_LIBRARY)
#  define CMLIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define CMLIBSHARED_EXPORT Q_DECL_IMPORT
#endif

ma​​ster-controller.h

#pragma once

#include <QObject>
#include <QString>
#include <cm-lib_global.h>

namespace cm::controllers {
class CMLIBSHARED_EXPORT MasterController : public QObject
{
    Q_OBJECT
    QString welcomeMessage = "This is MasterController to Major Tom";
    Q_PROPERTY( QString ui_welcomeMessage MEMBER welcomeMessage CONSTANT )
    public:
    explicit MasterController(QObject* parent = nullptr);
};
}

ma​​ster-controller.cpp

#include "master-controller.h"

cm::controllers::MasterController::MasterController(QObject* parent):
    QObject(parent)
{
}

cm-ui.pro

QT += qml quick

TEMPLATE = app
CONFIG += c++17
INCLUDEPATH += ../cm-lib

SOURCES += main.cpp

LIBS += -L"../build-cm-lib-Desktop_Qt_5_12_1_MinGW_64_bit-Debug\debug" -lcm-lib

ma​​in.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <master-controller.h>

int main(int argc, char *argv[])
{
    #if defined(Q_OS_WIN)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif

    QGuiApplication app(argc, argv);

    qmlRegisterType<cm::controllers::MasterController>("CM", 1, 0, "MasterController");

    cm::controllers::MasterController masterController{};

    QQmlApplicationEngine engine{};
    engine.rootContext()->setContextProperty("masterController", &masterController);
    engine.load(QUrl(QStringLiteral("qrc:/views/MasterView.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

【讨论】:

  • “未定义的引用很可能是由丢失的 moc 文件引起的。”:完全正确。还有更多原因,请参阅this question
  • 请注意,qmake 经常会报告“无事可做”。发生这种情况时,我关闭项目,删除构建目录,然后再次打开项目。 qmake 肯定会在这些条件下找到可做的事情。
【解决方案2】:

只需在 Q_PROPERTY 中将 MEMBER 更改为 READ 即可解决此问题 对我来说。

花了我几个小时 :) 不客气。

MasterController.h

    #ifndef MASTERCONTROLLER_H
    #define MASTERCONTROLLER_H
    #include <QObject>
    #include <QString>
    #include <cm-lib_global.h>

    namespace cm::controllers {
    class CMLIBSHARED_EXPORT MasterController : public QObject
    {
        Q_OBJECT
        QString welcomeMessage = "This is MasterController to Major Tom";
        Q_PROPERTY( QString ui_welcomeMessage READ welcomeMessage CONSTANT ) //<-----MEMBER to READ
        public:
        explicit MasterController(QObject* parent = nullptr);
    };
    }

顺便说一句:在错误消息(问题中包含的屏幕截图)中,您可以右键单击并在 qt 创建器中展开消息Show Output。通常,该错误在其中有一个 zickzackely 下划线。

【讨论】:

    【解决方案3】:

    您的代码本身没有问题并且可以编译,但是您在链接中缺少一个库。

    那是因为你 #include &lt;QGuiApplication&gt;,但是你在 .pro 的 thos 行中删除了 gui:

    QT       -= gui
    

    解决方案:

    QT       += gui <and any other libraries you've used, e.g. bluetooth>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 2022-01-22
      • 2016-04-04
      • 2015-11-03
      • 2011-08-11
      相关资源
      最近更新 更多