Qt

时间:2017-10-25 07:58:29

标签: qt vtable qobject

我无法使用“对CustomUndoStack的vtable的未定义引用”错误构建它

以下是代码:

class CustomUndoStack : public QObject
{
    Q_OBJECT

public:

};


int main(int argc, char *argv[])
{
    QCoreApplication qCoreApplication(argc, argv);

    CustomUndoStack uStack;

    return qCoreApplication.exec();
}

这是.pro文件:

QT += widgets

CONFIG += c++14 console
CONFIG -= app_bundle

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += main.cpp

我已经手动删除了构建目录,我尝试了所有可能的“全部清理”和“全部重建”,我运行了qmake 100500次,我已经将CustomUndoStack接口改为9000次,但没有帮助

问题出在哪里?

UPD回答评论:如果我删除Q_OBJECT行,那么我就不能这样做了。它说“没有这样的信号QObject :: undoSignal()”

class CustomUndoStack : public QObject
{
//    Q_OBJECT

public:
    CustomUndoStack() {
        connect(this, SIGNAL(undo_signal()), &undoStack, SLOT(undo()));
    }
signals:
    void undo_signal();
private:
    QUndoStack undoStack;
};

1 个答案:

答案 0 :(得分:4)

您的问题是由于您在QObject文件中声明了一个类的子类Q_OBJECT并且其中包含.cpp宏而引起的;该宏包含虚拟方法的声明:

virtual const QMetaObject *metaObject() const;

qmake工具仅处理头文件以定位包含QObject宏的Q_OBJECT子类,以自动生成与Q_OBJECT宏生成的声明相对应的实际代码。在您的情况下,qmake不处理main.cpp文件,因此它包含未实现的虚函数 - 因此您收到的链接器错误。

正确的解决方案是将类的声明移动到单独的头文件中,并将标头添加到项目中。然而,还有另一个解决方案,有点hacky但是如果你出于某些原因绝对需要将你的类的声明留在.cpp文件中,它可以被使用:

class CustomUndoStack : public QObject
{
    Q_OBJECT
public:
    CustomUndoStack(QObject * parent = 0) : QObject(parent) {}
};

#include "main.moc"

int main(int argc, char *argv[])
{
    QCoreApplication qCoreApplication(argc, argv);

    CustomUndoStack uStack;

    return qCoreApplication.exec();
}

注意#include "main.moc"行。此行的存在迫使qmake实际处理来自.cpp文件的声明,并生成所需的.moc文件,其中包含与Q_OBJECT生成的声明对应的自动生成的代码宏。