Qt出现“undefined reference to vtable for”原因总结

Qt编程常见错误解析
本文总结了Qt编程中常见的“undefined reference to vtable”错误及其解决方法,涉及宏Q_OBJECT的使用、moc工具的应用及链接问题等。

Qt出现“undefined reference to vtable for”原因总结
2009-06-24 01:50

由于Qt本身实现的机制所限,我们在使用Qt制作某些软件程序的时候,会遇到各种各样这样那样的问题,而且很多是很难,或者根本找不到原因的,即使解决了问题,如果有人问你为什么,你只能回答--不知道;
今天我在这里列举的问题也是再编写Qt程序时,总是遇到的问题,问题普遍,而答案却不唯一,解释这一个问题的说法很多,往往只适合某一种情况,因为这个错误太笼统了,它就是-- “undefined reference to `vtable for”可能你看着很熟悉,似乎在c++程序中也遇到过这个问题,你说对了,有时候这个错误,不只是qt的原因,还有你的c++程序的原因;

下面搜集了网上的一些出现的现象,对应解决方法,原因,基本上我都验证过,收录于此,以做备份;

一:
预编译器打开宏Q_OBJECT,声明若干个由moc处理(implement)的成员函数。如果得到类似于“undefined reference to vtable for LcdNumber”的编译错误(if you get compiler errors along the lines of "undefined reference to vtable for LcdNumber"),你可能是忘记了执行moc,或者忘记了将moc输出加入到link命令里。

某一个类中如果加入Q_OBJECT后,则link时提示:undefined reference to vtable for "xxx::xxx".删掉它则没有任何问题.

解决:尝试(1):把所有的obj文件和uic文件还有Makefile,Makefile.Debug,Makefile.Release和debug/release两个文件夹都删除,重新编译.
仍然失败.去trolltech的mail lists找到原因: 因为qmake生成Makefile的时候,这个类的头文件中并没有Q_OBJECT,所以在相应的Makefile里面并没有用moc xxx.h命令,最终导致链接失败.重新运行qmake,问题解决.
在查找解决方法的时候,附带发现一点:
qmake 不会处理.cpp文件里的Q_OBJECT,所以,如果在.cpp文件中有它的话,也会产生undefined reference to vtable for "xxx::xxx". 这时,需要先用moc xxxx.cpp生成相应的moc文件,再包含到.cpp里面去,才能解决这个问题.

这里可以发现问题的出现是因为没有moc生成相应的moc文件,之后连接就出问题。
我找了好多源码之类的问题,就是没有找pro的错误,后来想到qt中moc我们是有make做的
qt的make编译是根据Makefile来的,而Makefile是由pro文件来的。这才想到了找pro文件的错误。
from: http://www.cublog.cn/u/16292/showart_136087.html

二:

undefined reference to vtable for "xxx::xxx"
今天碰到了这个问题,终于被我google到了:
http://www.cublog.cn/opera/showart.php?blogid=8650&id=49526
原 因:qmake不会处理.cpp文件里的Q_OBJECT,所以,如果在.cpp文件中有它的话,也会产生undefined reference to vtable for "xxx::xxx". 这时,需要先用moc xxxx.cpp生成相应的moc文件,再包含到.cpp里面去,才能解决这个问题.
其他:
1.问题: QGLViewer中的函数不能正常link.解决: 翻看其源代码,发现是因为从源码安装libQGLViewer时,编译用了Qt 3,而我的程序中用Qt4 编译.所以必须重新用Qt4编译.但是,更改QTDIR 环境变量为Qt4后,重新编译的话,qmake生成makefile时就提示出错.进一步发现,是因为虽然设了QTDIR为Qt4,头文件和库文件都会使 用Qt4,但是moc,uic等都是用的qt3版的,再把PATH环境变量改动后,一切ok.
2.问题:某一个类中如果加入Q_OBJECT后, 则link时提示:undefined reference to vtable for "xxx::xxx".删掉它则没有任何问题.解决:尝试(1):把所有的obj文件和uic文件删除,重新编译.仍然失败.去trolltech的 mail lists找到原因: 因为qmake生成Makefile的时候,这个类的头文件中并没有Q_OBJECT,所以在相应的Makefile里面并没有用moc xxx.h命令,最终导致链接失败.重新运行qmake,问题解决.在查找解决方法的时候,附带发现一点:qmake 不会处理.cpp文件里的Q_OBJECT,所以,如果在.cpp文件中有它的话,也会产生undefined reference to vtable for "xxx::xxx". 这时,需要先用moc xxxx.cpp生成相应的moc文件,再包含到.cpp里面去,才能解决这个问题.
3. 看Qt的reference发现: 可以connect(pObjA, SIGNAL(someSignalA()),pObjB,SIGNAL(someSignalB()));这样pObjA发出的someSingalA 会导致pObjB发出someSignalB,从而形成信号接力.

from:http://blog.donews.com/netexe/archive/2006/02/09/720544.aspx

三:
编译报错的部分是:


CODE:[Copy to clipboard]tmp/obj/release_shared/myplot.o(.text+0x194):myplot.cpp: undefined reference to
`vtable for MyPlot'
tmp/obj/release_shared/myplot.o(.text+0x19b):myplot.cpp: undefined reference to
`vtable for MyPlot'
tmp/obj/release_shared/myplot.o(.text+0x934):myplot.cpp: undefined reference to
`vtable for MyPlot'
tmp/obj/release_shared/myplot.o(.text+0x93b):myplot.cpp: undefined reference to
`vtable for MyPlot'
collect2: ld returned 1 exit status
你 MyPlot 是不是声明了什么 virtual 的 方法, 但在实现(cpp)文件里没有实现。
看了一下, 现在推测一下。 MyPlot 继承了 QwtPlot, 现在报的这个错, 应该是这个意思,
1. QwtPlot 里含有 vritual 方法, 所以你的继承类需要一个 virtual 的析构函数
2. QwtPlot 里含有 纯虚的方法, 你没有继承, 而这个可能性比较小


所以, 你可以:
在MyPlot里声明一下一个虚的析构函数
virtual ~MyPlot() {}

我们来看一个简单些的例子吧:


CODE:[Copy to clipboard]#include <qapplication.h>
#include <qpushbutton.h>

class myWidget :public QWidget
{
Q_OBJECT
public:
       myWidget(QWidget *parent = 0);
public slots:
       void shutDown();
private:
        QPushButton *exit;
};

myWidget::myWidget(QWidget *parent):QWidget(parent)
{
                           setMinimumSize(120, 180);
                           setMaximumSize(120, 180);
                           exit = new QPushButton("ShutDown!",this);
                           connect(exit,SIGNAL(clicked()),this,SLOT(shutDown()));
}

void myWidget::shutDown()
{
     system("halt");
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    myWidget *w = new myWidget();
    w->show();
    app.exec();
}
还是报错:


CODE:[Copy to clipboard]shut.o(.text+0x21): In function `myWidget::myWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
shut.o(.text+0x28): In function `myWidget::myWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
shut.o(.text+0x141): In function `myWidget::myWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
shut.o(.text+0x148): In function `myWidget::myWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for myWidget'
collect2: ld returned 1 exit status
这是我从l搜索引擎上搜到的例子,从代码中好像看不到明显的错误吧
我自己试了一下编译也是出错

刚才那个简单的例子的原因可能是这样的:


QUOTE:
2.问题:某一个类中如果加入Q_OBJECT后,则link时提示:undefined reference to vtable for "xxx::xxx".删掉它则没有任何问题.


解决:尝试(1):把所有的obj文件和uic文件删除,重新编译.仍然失败.


去trolltech的mail lists找到原因: 因为qmake生成Makefile的时候,这个类的头文件中并没有Q_OBJECT,所以在相应的Makefile里面并没有用moc xxx.h命令,最终导致链接失败.重新运行qmake,问题解决.


在查找解决方法的时候,附带发现一点:


qmake不会处理.cpp文件里的Q_OBJECT,所以,如果在.cpp文件中有它的话,也会产生undefined reference to vtable for "xxx::xxx". 这时,需要先用moc xxxx.cpp生成相应的moc文件,再包含到.cpp里面去,才能解决这个问题.
知道你的问题了, 上面的例子不好, 因为你这个把main和类放在一起了。 如果分开, 可能就没问题, 包括 h和 cpp 分开。

要解决上面的问题, 在你main.cpp 最后加一行
#include "main.moc"

然后把除了 main.cpp 的其它文件都删了。重新来, 没问题的。

所以, 我估计你前面提到的问题也是没有链接 moc 文件。 你在你的 myplot.cpp 文件最后加一行: #include "myplot.moc" 试试看。


另外: 你main 没有返回值, 编译会警告, 而且程序最后一行不是只含有回车, 也会警告。


这是一个论坛贴,完整讨论请看:http://www.myswear.net/forum/viewthread.php?tid=5177&extra=&page=1


四:

Qt自己也有对这个的解释:
http://www.qtopia.org.cn/doc/4.1/signalsandslots.html

差不多了,我今天遇到了一个更诡异的,几个文件单独编译都没有问题,就是链接出现错误,最后信手删掉报错文件中的某个宏定义(此宏定义是定义是否只是用qt的一个定义),然后,就ok了,你说怪不怪,我现在也没想通原因;faint。。。Qt还真是折磨人。。。

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/baymoon/archive/2006/11/23/1409167.aspx

### 解决 CMake 构建 Qt 项目时出现的 `undefined reference to vtable` 错误 当遇到 `undefined reference to vtable for MainWindow` 的错误时,这通常意味着元对象编译器 (Meta-Object Compiler, moc) 没有正确处理类中的信号和槽机制。此类问题可以通过多种方法来解决。 #### 方法一:确保 MOC 正确运行 为了使 MOC 能够正常工作,在 CMakeLists.txt 文件中应包含如下设置: ```cmake find_package(Qt5 COMPONENTS Widgets REQUIRED) add_executable(${PROJECT_NAME} main.cpp mainwindow.cpp) target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets) set(CMAKE_AUTOMOC ON) # 自动调用MOC工具 ``` 通过开启自动 MOC 功能 (`set(CMAKE_AUTOMOC ON)`)[^3],可以简化项目的配置过程并减少手动干预的需求。 #### 方法二:清理构建缓存 有时旧的构建产物可能会干扰新的编译流程。建议删除整个 build 目录再重新执行完整的构建命令链: 1. 删除现有的 build 文件夹; 2. 创建一个新的 build 文件夹; 3. 进入新创建的 build 文件夹; 4. 执行 `cmake ..` 和 `make` 命令完成重建[^4]。 这种方法有助于排除由于残留文件引起的各种潜在冲突。 #### 方法三:验证头文件声明 确认所有的虚函数都已经在 .h 头文件中有相应的定义,并且这些类继承自 QObject 或其子类的同时也使用 Q_OBJECT 宏进行了标记。例如: ```cpp #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); private slots: void handleButtonClicked(); }; #endif // MAINWINDOW_H ``` 上述代码片段展示了如何在一个窗口部件类中正确定义 Q_OBJECT 宏以及关联的方法签名[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值