前言
最近在复习一些 C++基础知识,写了一些 C++的代码,当我在类中定义了虚函数并且直接在类定义内部实现这些虚函数时,编译器就会报警告:’xxx‘ has no out-of-line virtual method definitions;its vtable will be emitted in every translation unit.
如下图:
如何解决
以前好像从来没留意过这些问题,然后决定找找原因,后来查了一些资料终于找到真正的原因,来看一段话:
If a class is defined in a header file and has a vtable (either it has virtual methods or it derives from classes with virtual methods), it must always have at least one out-of-line virtual method in the class. Without this, the compiler will copy the vtable and RTTI into every .o file that #includes the header, bloating .o file sizes and increasing link times
这里大概意思就是:
如果在头文件中定义了一个类并且具有vtable(它具有虚方法或者它来自具有虚方法的类),则它必须始终在类中具有至少一个外联虚拟方法。 如果没有这个,编译器会将vtable和RTTI复制到每个.o文件中,其中#include标题,膨胀.o文件大小和增加链接时间。
也就是说,当类中定义了虚函数时,编译器会自动生成虚函数表vtable,用来对应每一个虚函数。那么,如果所有虚拟方法都是内联的(在头文件中定义),那么编译器不知道哪个翻译单元(.cpp文件)在其中发出vtable,因此它会在所有这些中发出一个副本,并且链接器会处理用它。这会在目标文件中产生额外的工作和并且是.o文件变得更庞大。另一方面,如果虚拟函数是在线外定义的(在.cpp中),则可以在那里发射vtable,因此只会发出一个副本。
所以知道以上原因过后,解决方法就很简单了,因为我是在类中定义了虚函数并且直接在类定义内部实现这些虚函数,所以将虚函数自动变成了内联函数,那么只需要把虚函数的实现挪到类的外面去实现就可以啦。
反思
1.本是一个习惯性的操作,有时候觉得定义的函数实现比较简单,所以就直接在类定义中实现,这就自动变成了内联函数,但是没想过不同的函数类型可能会带来不同的影响。
2.不要忽视编译器警告。通常我们在写代码,只要没出错就觉得万事大吉了,很少会去留意警告信息,但是其实警告信息也非常重要,因为它可能会成为今后软件出问题的一个导火线。
3.知其然,知其所以然。了解一些编译器的工作原理可以更有助于去改善代码质量。之前在看《深度探索C++对象模型》时深有感触。
原文链接:https://blog.csdn.net/luoyayun361/article/details/88369950