c++ - C++在构造函数中调用最终的虚函数
问题描述
确实,在构造函数和析构函数中调用虚函数不是一个好习惯,应该避免。这是因为虚函数受子类的影响,但在构造或销毁阶段,子类尚未构造(构造中)或已被破坏(销毁中)。
但是,如果在构造函数或析构函数中调用虚拟最终函数会发生什么?我认为应该没有问题,因为它在逻辑上没有错。
禁止在构造函数和析构函数中调用虚函数,因为在子类中声明的虚函数的重写版本中可能会访问尚未初始化的子类变量。
虽然 virtual final 函数不是,但它是 final 并且无法访问子类的变量。
但这是我的假设,在构造函数或析构函数中调用虚函数不合理可能还有更多原因。
所以,总而言之,
- 在 C++ 标准中是否允许在构造/销毁阶段调用虚拟最终函数?
- 如果是这样,它是否广泛应用于大多数 C++ 编译器?
- 如果不是,那有什么理由吗?
解决方案
在 C++ 标准中是否允许在构造/销毁阶段调用虚拟最终函数?
在构造/销毁期间调用虚函数是明确定义的并且完全合法,除了纯虚函数的情况。
禁止在构造函数和析构函数中调用虚函数
我不知道(也不在乎)从风格的角度,代码维护的角度来看,谁说它是“坏的”或“禁止的”......维护代码的能力首先取决于对相关语言和工具的了解;不知道虚拟调用在这些阶段做了什么(*)会导致维护人员的误解,通过选择更有经验的维护人员而不是降低编程风格来解决这个问题。
(*)在技术上不是对象“生命周期”的一部分,这甚至不是一个非常有用的概念,因为对象在任何非平凡程序(我认为标准应该简单地压制这个不需要的概念)。
访问子类的变量(尚未初始化)可能发生在子类中声明的虚函数的重写版本中。
它不能。在基类子对象的构造过程中B
(例如通过构造函数B::B()
),正在构造的对象的类型是由定义的B
。
虚函数的重写版本,在子类中声明。
不,此时没有现有的子类对象,因此没有覆盖。
虽然 virtual final 函数不是,但它是 final 并且无法访问子类的变量。
没有什么不同的。
多态对象的动态类型由构造函数在基类的构造函数之后和构造成员之前建立。
如果是这样,它是否广泛应用于大多数 C++ 编译器?
实际上,所有编译器都通过更改一个或多个 vtable 指针以指向该类型的适当 vtable 来实现设置对象的动态类型;这是作为施工的一部分完成的。
这意味着在构造过程中,vptr 值会随着派生对象的构造而变化。
推荐阅读
- javascript - 工作箱服务工作者
- java - JPA:使用 em.createNativeQuery 在 INSERT 或 UPDATE 后检索自动生成的密钥
- jquery-ui - 定位弹出式键盘
- java - Java Graphics 2D 渲染质量问题
- python - 我想在 Opencv python 上连接列表
- node.js - 带有计算字段的mongodb查找
- java - 无法启用 Android Studio 存储库
- sql-server - 带有 .NET 调用堆栈的 SQL Server Profiler
- javascript - 使用 RandomTimeOut ( Javascript ) 维护输出顺序
- node.js - 如何创建基于节点的服务器来服务 REST API 并部署应用程序。