Qt undefined reference to `vtable for * * * '

2020-04-23 11:46:18 浏览数 (1)

缘起:

最近想写个demo验证Qt connect在第五个参数不同的情况下,各自槽函数运行在哪个线程中。为了简便,就没有创建.h和.cpp文件,直接在main函数中写的,结果在运行时就出现了 undefined reference to `vtable for * * * '这种错误。

代码如下:

代码语言:javascript复制
class SendMsg : public QObject
{
    Q_OBJECT
};

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

SendMsg sendMsg;

    return a.exec();
}

经过谷歌,再结合自己的验证,做个总结。

1. GCC 常见问题之一

When building C , the linker says my constructors, destructors or virtual tables are undefined, but I defined them

The ISO C Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.

Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.

The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]

简单来说,C 标准规定:对于类内所有非纯虚函数的虚方法必须被定义,而且对于未遵循该规定的代码不做提示。所以我的程序直接在链接时提示上述错误。

2. Qt 中是怎样出现该问题的

①当把类SendMsg的声明放在单独的.h文件中,无上述错误

当时测试时,为了简便,我直接放在了main.cpp中,所以出现了上述错误。如果将类SendMsg的声明单独放在.h中,则没有上述错误。在Qt中说明如下(Using the Meta-Object Compiler (moc)):

元对象编译器moc是处理Qt的C 扩展的程序。

moc工具读取C 头文件。 如果找到一个或多个包含Q_OBJECT宏的类声明,它将生成一个C 源文件,其中包含这些类的元对象代码。 除此之外,信号和槽机制,运行时类型信息和动态属性系统也需要元对象代码。

必须编译由moc生成的C 源文件,并与该类的实现链接。

②结论

由以上可知,moc是从头文件中读取程序的,所以放在main.cpp的程序无法生成新的c 文件。

3. 解决方法

①将类SendMsg的声明放在单独的.h文件中,可自动生成moc文件

②手动生成.moc文件

在Qt安装目录下,找到moc.exe工具,手动生成.moc文件

手动生成.moc文件方法

生成.moc文件效果

现在程序变成这样:

代码语言:javascript复制
class SendMsg : public QObject
{
    Q_OBJECT
};

#include "main.moc"


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

    SendMsg m_sendMsg;

    return a.exec();
}

Moc文件部分函数:

QObject 宏中声明的未实现的虚方法:

看到这里,你也就知道了由于上面三个虚函数没有被实现,所以会有undefined reference to `vtable for * * * '这种错误。

4. 小结

认真生活, 努力感悟!

0 人点赞