error: undefined reference to ‘vtable for …’

7 篇文章 0 订阅
2 篇文章 0 订阅

error: undefined reference to ‘vtable for …’

这个报警就是子类没有实现父类的纯虚函数,奇怪的是自定义的虚函数都已经进行了定义,这个时候需要留意还有一种情况就是Qt中一个类继承了QObject,而且添加了Q_OBJECT宏,此时就可能出现上面的异常。

原理

测试源码

object.h:
#ifndef OBJECT_H
#define OBJECT_H
#include <QObject>
class Object : public QObject
{
    Q_OBJECT                        // 增加删除这个宏然后再编译
public:
    explicit Object(QObject *parent = 0);
};
#endif // OBJECT_H
object.cpp:
#include "object.h"
Object::Object(QObject *parent) :
    QObject(parent)
{
}
main.cpp:
#include <QtCore/QCoreApplication>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    return a.exec();
}

Makefile

在Object类中分别添加和删除Q_OBJECT宏,查看对应的两份Makefile:

不包含Q_OBJECT

当一个类中不包含Q_OBJECT,生成的makefile是这样的(精简):

OBJECTS = main.o \
		  object.o
TARGET        = test2
first: all
all: Makefile $(TARGET)

$(TARGET):  $(OBJECTS)  
	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)

Makefile: test2.pro
	$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ -o Makefile test2.pro

main.o: main.cpp 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp

object.o: object.cpp object.h
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o object.o object.cpp

重新编译的操作:

15:35:55: 为项目test2执行构建步骤 …
15:35:55: 正在启动 “/usr/bin/make” clean -w
{1"?} {2?}
make: Entering directory /home/u/delete/test2/test2' rm -f main.o object.o rm -f *~ core *.core make: Leaving directory /home/u/delete/test2/test2’
15:35:55: 进程"/usr/bin/make"正常退出。
15:35:55: 配置没有改变, 跳过 qmake 步骤.
15:35:55: 正在启动 “/usr/bin/make” -w
{1"?} {2?}
make: Entering directory /home/u/delete/test2/test2' g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -o main.o main.cpp g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -o object.o object.cpp g++ -Wl,-O1 -o test2 main.o object.o -L/usr/lib/i386-linux-gnu -lQtCore -lpthread make: Leaving directory /home/u/delete/test2/test2’
15:35:55: 进程"/usr/bin/make"正常退出。

包含Q_OBJECT

当一个类中包含Q_OBJECT的时候,对应的makefile是这样的(精简):

OBJECTS = main.o \
		  object.o \
		  moc_object.o
TARGET        = test2
first: all

all: Makefile $(TARGET)

$(TARGET):  $(OBJECTS)  
	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)

Makefile: test2.pro
	$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ -o Makefile test2.pro

moc_object.cpp: object.h
	/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) object.h -o moc_object.cpp

main.o: main.cpp 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp

object.o: object.cpp object.h
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o object.o object.cpp

moc_object.o: moc_object.cpp 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_object.o moc_object.cpp

然后有意思的就来了,重新编译的操作如下:

15:34:24: 为项目test2执行构建步骤 …
15:34:24: 正在启动 “/usr/bin/make” clean -w
{1"?} {2?}
make: Entering directory /home/u/delete/test2/test2' rm -f moc_object.cpp rm -f main.o object.o moc_object.o rm -f *~ core *.core make: Leaving directory /home/u/delete/test2/test2’
15:34:24: 进程"/usr/bin/make"正常退出。
15:34:24: 配置没有改变, 跳过 qmake 步骤.
15:34:24: 正在启动 “/usr/bin/make” -w
{1"?} {2?}
make: Entering directory /home/u/delete/test2/test2' g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -o main.o main.cpp g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -o object.o object.cpp /usr/bin/moc-qt4 -DQT_WEBKIT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. object.h -o moc_object.cpp g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -o moc_object.o moc_object.cpp g++ -Wl,-O1 -o test2 main.o object.o moc_object.o -L/usr/lib/i386-linux-gnu -lQtCore -lpthread make: Leaving directory /home/u/delete/test2/test2’
15:34:25: 进程"/usr/bin/make"正常退出。

两者区别

从两种重新编译的具体执行过程来看,重新编译精简理解就是:

make clean
make

当一开始编译一份不含Q_OBJECT宏的类时,他会生成一份Makefile,这份Makefile是基于没有Q_OBJECT宏qmake创建出来的,以本章例子为例,创建出来的Makefile并没有依赖moc_object.cpp,也没有创建该源文件的依赖生成关系;而该源文件就是Q_OBJECT宏对应的接口实现,因此,当仅修改头文件、在一个类中添加Q_OBJECT宏,此时即使是重新编译,由于.pro文件并没有变更,因此Makefile也没有变化,还是基于原先的逻辑进行编译,导致缺少对应的函数实现,进而导致编译器报警缺少函数实现的错误。

解决

处理方法就是重新qmake一下,也可以修改pro文件进而引发重新生成Makefile。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值