C++使用信号槽来为QML提供支持

8

我有一个小的类无法正常工作,但我不知道出了什么问题。编译器显示以下信息:

main.cpp: error: undefined reference to 'CDetails::CDetails()'

以下是代码快照:

//main.cpp
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QQmlContext>
#include <QDebug>

class CDetails : public QObject
{   Q_OBJECT
    public:
        CDetails() {}
        ~CDetails(void) {}


    public slots:
        void cppSlot(const QString &msg)
        {    qDebug() << "Called the C++ slot with message:" << msg;
        }
};

int main(int argc, char *argv[])
{   QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/testqml/main.qml"));
    viewer.showExpanded();

    CDetails *test = new CDetails();
    QObject::connect((QObject*)viewer.rootObject(),
                 SIGNAL(qmlSignal(QString)),test,
                 SLOT(cppSlot(QString)));
    return app.exec();
}

在main.qml中:

import QtQuick 2.0
Rectangle {
    id: guide
    width: 360
    height: 360
    signal qmlSignal(string msg)
    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    property double scaleFactor: 1.0
    property string iconUrl: "image.png"
    MouseArea {
        anchors.fill: parent
        onClicked: {
            guide.qmlSignal("Hello from QML")
        }
    }
}

更新: 感谢对构造函数提出的建议。现在错误是:
error: undefined reference to 'vtable for CDetails'

这里错过了什么?欢迎提出所有建议。

我不理解所选答案如何解决“error: undefined reference to 'vtable for CDetails'”问题。我想知道是否我漏掉了什么? - László Papp
@LaszloPapp - 我遵循了PavelStrakhov的建议:“你应该将类放在单独的头文件和源文件中”。这个方法行得通! - Judith
2个回答

6

错误:未定义对“CDetails的虚函数表”的引用

这里缺少什么?欢迎所有建议。

看起来您在主函数之前缺少了moc包含。

main.cpp

#include <QtGui/QGuiApplication>
#include <QQmlContext>
#include <QDebug>

class CDetails : public QObject
{   Q_OBJECT
    public:
        CDetails() {}
        ~CDetails(void) {}


    public slots:
        void cppSlot(const QString &msg)
        {    qDebug() << "Called the C++ slot with message:" << msg;
        }
};

#include "main.moc"

int main(int argc, char *argv[])
{   QGuiApplication app(argc, argv);
    QQuickView view;
    viewer.setMainQmlFile(QStringLiteral("qml/testqml/main.qml"));
    viewer.showExpanded();

    CDetails *test = new CDetails();
    QObject::connect((QObject*)viewer.rootObject(),
                 SIGNAL(qmlSignal(QString)),test,
                 SLOT(cppSlot(QString)));
    return app.exec();
}

main.pro

...
TEMPLATE = app
TARGET = main
QT += quick
SOURCES += main.cpp
...

请注意,您还需要添加之前存在的自定义行,例如处理应用程序查看器等。
或者,您也可以将类和main.cpp解耦,这意味着您将把类的声明放入单独的头文件中,然后将其定义放入单独的源文件中。
main.cpp将包括新建立的头文件,并且您需要确保将新的头文件和源文件分别添加到qmake项目文件中的HEADERS和SOURCES变量中,以通过moc处理。

1
实际上,您可以将所有方法的声明和实现放在头文件中。但是类的声明必须在头文件中,而不是在main.cpp中。 - Pavel Strakhov
@Pavel:那不是真的。我已经写了几个只有简单Q_OBJECT类的main.cpp项目,它们都在main.cpp中。关键是要包含生成的moc文件。 - László Papp
@LaszloPapp - 我想 PavelStrakhov 的评论有些道理。我尝试包含 main.moc,但是它会出现错误:“没有这样的文件或目录”。没有 main.moc,代码可以工作,但也必须像 TanyaKadam 建议的那样添加 qtquick2applicationviewer.pri。但感谢所有的输入和评论。 - Judith
@LaszloPapp - 刚刚做了那个。采纳了建议,使用qmake重新构建并重新运行它。现在关于main.moc的错误显示为:{没有生成目标“main.moc”,需要“main.o”。停止}。但是如果我去掉main.moc,那么它至少对于嵌入式来说可以正常运行。 - Judith
@LaszloPapp - 是的。我已经运行它并且它可以正常工作,没有出现任何问题。感谢您提供的所有反馈。 - Judith
显示剩余4条评论

4

您缺少构造函数和析构函数的实现。快速修复:

class CDetails : public QObject
{   Q_OBJECT
public:
  CDetails() {}
  ~CDetails(void) {}
   ...
};

谢谢。我已经修改了那个。请检查更新。现在出现了另一个错误。 - Judith
1
Q_OBJECT 必须在头文件中。你应该将类放到单独的头文件和源文件中。 - Pavel Strakhov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接