C++ warning:’xxx‘ has no out-of-line virtual method definitions...

前言

最近在复习一些 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

原文地址:https://www.cnblogs.com/Vancamel/p/11781301.html

时间: 2024-08-28 23:16:19

C++ warning:’xxx‘ has no out-of-line virtual method definitions...的相关文章

Windows下Git使用报错:warning:LF will be replaced by CRLF in ××××.××

Windows下Git使用报错: warning:LF will be replaced by CRLF in ××××.××(文件名) The file will have its original line ending in your working directory. 翻译: 在xxx.xx文件中LF将被CRLF替换. 在工作区(working directory)里,这个文件将会保持它原本的换行符.(line ending:行尾,换行) 注解:           LF:Line F

Android - Warning:Not annotated parameter overrides @NonNull parameter

Warning:Not annotated parameter overrides @NonNull parameter 本文地址:http://blog.csdn.net/caroline_wendy Warning:The @NonNull annotation can be used to indicate that a given parameter can not be null. "@NonNull"的含义是注释非空,如果出现以上警告,就表明参数应该有非空标注: 如添加:

使用hql查询时的异常:Xxx is not mapped[from Xxx where ...]

今天项目中使用hql查询时,出现    QingAoCenterInfo is not mapped[from QingAoCenterInfo where...] 显然是Hibernate映射关系出现了问题. 出现这种异常首先要查看查询语句中是否使用了数据库表中的表名,而不是实体类. 查看我的代码: centerList = manager.find("from QingAoCenterInfo center where center.type = ? and center.centerNam

warning:deprecated conversion from string constant to 'char *'

warning:deprecated conversion from string constant to 'char *' 解决方案 #include <iostream> using namespace std; int fuc(char *a) { cout << a << endl; } int main() { fuc("hello"); } Linux 环境下当GCC版本比较高时,编译代码可能出现的问题. 主要原因是: char * 指针

【MySQL案例】error.log的Warning:If a crash happens thisconfiguration does not guarantee that the relay lo

1.1.1. If a crash happens thisconfiguration does not guarantee that the relay log info will be consistent [环境描述] msyql5.6.14 [报错信息] mysql的slave启动时,error.log中出现Warning警告: [Warning] Slave SQL: If a crash happensthis configuration does not guarantee tha

关于 Tomcat 6.0:&quot;XXX&quot; does not exist or is not a readable directory 问题的解决办法

问题描述:将项目部署到Eclipse集成的Tomcat服务器中中的时候,控制台报错:XXX does not exist or is not a readable directory . 出现原因:直接在Tomcat工作目录下,将之前部署的项目删除,而Tomcat不知道已经删除. 解决办法: 方法一:[实测有效]简单粗暴,操作方便[推荐] 将Eclipse中现集成好的Tomcat服务器删除"Delete",然后重新配置一个新的Tomcat服务器,将项目部署到服务器中,启动服务器,观察服

Python:XXX missing X required positional argument: &#39;self&#39;

代码的一个小小Bug有时候会让人焦头烂额,费了很大劲搞明白的问题,如果不记录下来,是很容易遗忘的! 定义一个类,如果按照以下的方式使用,则会出现TypeError: testFunc() missing 1 required positional argument: 'self'.如果认真细究的话,笔者曾反复修改参数,但是于事无补. 在Python中,应该先对类进行实例化,然后在应用类,如下图所示.注意,实例化的过程是应该待括号的. 总结:Python中,类应该先实例化,然后再使用类! Pyth

UBuntu sudo 命令 :xxx is not in the sudoers file. This incident will be reported.

[1]分析问题 提示内容翻译成中文即:用户XXX(一般是新添加的用户名称)没有权限使用sudo. 解决方法修改新用户的权限,具体操作即修改一下/etc/sudoers文件. [2]切换至root用户模式 命令:su - 备注:这里命令加有"-" ,与su是不同的. 在用命令"su"时只是切换到root,但没把root的环境变量传过去,还是当前用户的环境变量. 而用"su -"命令会将环境变量也一起切换过去(可以亲测,两个命令后分别查看环境变量$P

MYSQL报警:Warning: Using a password on the command line interface can be insecure.

问题描述:执行下面的语句,sql是执行成功了,但是出现了一个报警,报警看上去始终不舒服 mysql -hip -Pport -uuser -ppassword -e "use db;delete from tb;"; Warning: Using a password on the command line interface can be insecure. 解决方法:报警的意思是“在命令行输入密码是不安全的”,解决方法是将用户名和密码写入配置文件,然后在命令行用参数的形式引入文件