未定义对vtable的引用。尝试编译Qt项目。

56

我正在使用Code::Blocks 8.02和mingw 5.1.6编译器。在编译我的Qt项目时,我遇到了以下错误:

C:\Documents and Settings\The Fuzz\Desktop\GUI\App_interface.cpp|33|undefined reference to `vtable for AddressBook'

文件AddressBook.h:

 #ifndef ADDRESSBOOK_H
 #define ADDRESSBOOK_H

 #include <QWidget>

 class QLabel;
 class QLineEdit;
 class QTextEdit;

 class AddressBook : public QWidget
 {
     Q_OBJECT

 public:
     AddressBook(QWidget *parent = 0);

 private:
     QLineEdit *nameLine;
     QTextEdit *addressText;
 };

 #endif

文件 AddressBook.cpp:

#include <QtGui>
#include "addressbook.h"

AddressBook::AddressBook(QWidget *parent)
     : QWidget(parent)
{
    QLabel *nameLabel = new QLabel(tr("Name:"));
    nameLine = new QLineEdit;

    QLabel *addressLabel = new QLabel(tr("Address:"));
    addressText = new QTextEdit;

    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(nameLabel, 0, 0);
    mainLayout->addWidget(nameLine, 0, 1);
    mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop);
    mainLayout->addWidget(addressText, 1, 1);

    setLayout(mainLayout);
    setWindowTitle(tr("Simple Address Book"));
}
21个回答

53

在使用Qt Creator时:

  1. 构建 → 运行 qmake
  2. 构建 → 重新构建全部

3
这个答案误导了读者。如果问题提出者使用的是Qt Creator,那么这个解答是没有问题的。但问题提出者只提到了Code::Blocks。据我所知,Code::Blocks的构建菜单中没有run qmake选项,也没必要加入这样一个选项。我可以相信一个插件会添加这样一个选项,但问题提出者并没有提到使用任何第三方插件。很可能问题提出者仍需要运行qmake,但是告诉他们使用一个可能不存在的菜单选项是不会有帮助的。 - Samuel Harmer
正确,如果不使用Creator,则解决方案只需从命令提示符中运行“qmake”。 - peppe
运行qmake,然后运行make以获得确切的效果 - 仅运行make会生成make文件。实际上是一个有误导性的名称。 - nerdguy

47

警告:如果您已经有 .pro 文件,请不要这样做 - 您将失去它!

为了自动确保生成所有 moc cpp 文件,您可以让 qmake 自动为您生成 .pro 文件,而不是自己编写一个。

运行

qmake -project

在项目目录下,qmake会扫描您的所有C++头文件和源代码文件,并生成moc cpp文件。


3
我和楼主遇到了完全相同的问题,但在我的情况下,重新运行qmake并不能解决它。这只是一个部分解决方案,仅适用于一些人。 - DarenW
1
DarenW:检查包含类声明的头文件是否在HEADERS列表中。 - Frank Osterfeld
1
DarenW:谢谢,这很有帮助。我已经思考了3个小时了。这是什么问题?我没有手动编写qmake。这是QT的漏洞吗?为什么我们已经写得正确,但它却不能编译? - Tebe
6
不要运行这个命令。这将清除您的.pro文件和其中的任何修改。只需单独运行qmake(从命令行或Creator中的构建菜单),就足以完成任务。 - peppe
3
这个答案是错误和危险的。就这样。除非您从头开始并没有现有的 .pro 文件,否则永远不必这样做! - Kuba hasn't forgotten Monica

16
问题几乎肯定是您没有编译或链接生成的moc_AddressBook.cpp文件。(它应该已经为您生成 - 您是否在编译之前运行了Qt的 moc 工具来处理您的代码?)
更详细地说,Q_OBJECT 宏会向 Qt 的 moc 工具发出信号,要求创建一个额外的实现文件,其中包含支持 QObject 元信息系统所需的代码。如果有任何信号或槽函数,它还会执行一些其他操作。
另一种解决方案可能是删除 Q_OBJECT 宏。您可能不想这样做,但这将有助于解决当前的问题,而且对于您提供的代码来说并不是完全必要的。
另外,我想指出您的这行代码:
#include "addressbook.h"

建议改为:

#include "AddressBook.h"

根据您在问题中展示的文件名来看。


Windows文件系统不区分大小写。 - CMircea
13
即使在Windows上,您仍应该注意大小写。这在Unix上非常让人恼火,因为原始开发者在Windows上不关心大小写问题,导致在检出项目时需要手动修复这些问题。 - Etienne Perot

10

假设您正在使用qmake生成Makefile,请确保在.pro文件的HEADERS变量中指定了AddressBook.h,例如:

HEADERS = AddressBook.h

请提供实际答案,不要讨论特定平台/IDE或原因,清晰易懂且可用。谢谢。 - Croll
使用QTCreator时,您可以在项目的“Headers”部分中添加文件(它会将其添加到.pro文件中的HEADERS变量中)。 - Paul Hutchinson
QtCreator可能会在.pro文件的HEADERS变量的第二行上添加您的头文件名称。然后第一行将是"HEADERS +=",这样是行不通的。删除第一个空条目并将其更改为(在此示例中):"HEADERS += AddressBook.h"。 - SR_

6
对于CMake项目,请将CMAKE_AUTOMOC设置为ON,这样可以解决我的问题。
#Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)

4

我在使用纯虚函数时遇到了这个问题。例如,

virtual void process();

在执行操作时出现了以下错误:

virtual void process() = 0;

帮助解决问题的方法是检查所有虚函数是否已经定义。(通过“= 0”或在源文件中进行完整定义)我正在使用MinGW编译器的Netbeans。

如果有人正在谷歌这个问题,希望这可以让问题消失。


我在Ubuntu下使用Qt Creator 1.3也遇到了同样的问题,这个方法对我有用。但是我不知道根本原因是什么。 - Martin

4

2

我曾经遇到过同样的问题,但是当我在头文件中定义构造函数而不是.cpp文件时,错误消失了。此外,在文件系统和Makefile部分“compiler_moc_header_make_all”中缺少相应的moc文件。我运行了qmake,最终一切都成功地构建了。我查看了Makefile,现在它已经存在了。


2

删除了构建文件夹,重新启动Qt Creator,问题得到解决。


这可能对你有用,但是考虑到OP没有使用Qt Creator,它并不是很相关。 - paxdiablo

1
只需清除项目,然后重新构建即可!

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