首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++子构造函数和VPTR

C++子构造函数和VPTR
EN

Stack Overflow用户
提问于 2014-12-04 14:23:52
回答 2查看 411关注 0票数 0

在许多源中,书籍等都是“不要调用它->子类构造函数中的虚拟函数”,并且在某些来源中解释了为什么不能这样做。因为在构建的时候,类根本没有被创建。因此,从子构造函数调用的虚拟函数将是基类的函数。这意味着在子构造函数体中,该类的VPTR指向基VTABLE。

所以我的问题是,

当子类的VPTR被覆盖到它的虚拟表上时,对象构造的时刻是什么时候?我猜一些自动生成的代码会在构造函数体的末尾或构造函数体执行之后执行。

第二个问题是,

为什么VPTR在施工结束时会过度使用?也许是因为它有一些重要的原因?为什么不能在开始构造函数体或基类构造之后重写VPTR?

代码语言:javascript
复制
Child::Child() :
Base()
//<----- Why not here?
//members initialization
{
//<----- Why not here?
//code
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-04 14:42:31

在许多来源中,书籍等都写成“不要调用这个->子类构造函数中的虚拟函数”。

我怀疑这一点。通常建议不要从基类构造函数调用虚拟函数,以避免混淆,如果您期望它们调用最终重写,而不是基类版本。如果它们是纯虚拟的,那么当然不能从基类中调用它们--这就产生了未定义的行为。

在派生类构造函数中,它们是定义良好的,可以执行您期望的操作。

因此,从子构造函数调用的虚拟函数将是基类的函数。

不,在子构造函数的主体中,动态类型是Child,虚拟函数调用将使用Child覆盖。

当子类的VPTR被覆盖到它的虚拟表上时,对象构造的时刻是什么时候?

在所有基类构造函数完成之后,以及在初始化子类成员之前。Child成员函数(包括虚拟函数)可以从成员初始化程序(但不是基类初始化程序)或构造函数体调用。

您需要小心地从成员初始化器中调用它们,因为它们可能访问未初始化的成员。但是在构造函数体中,所有基本对象和成员都是初始化的,因此它们是相当安全的。

为什么VPTR在施工结束时会过度使用?

它不是,它发生在您用<----- Why not here?表示的第一点。

票数 1
EN

Stack Overflow用户

发布于 2014-12-04 14:35:04

我不同意你过于简化的理由,为什么你不应该调用一个虚拟函数。首先,VTABLE实际上不是由C++标准定义的,实际上是特定于实现的:

When is VTable in C++ created?

标准允许从构造函数调用虚拟函数,实际上应该在该级别的层次结构中正确调用(但有一些限制)。

C++ constructors: why is this virtual function call not safe? http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctors.html

然而,有很多很多原因不这样做。

  • 尚未调用派生类的构造函数。派生类的任何成员的任何访问都会产生未定义的行为。
  • 有一个经验法则,你应该让构造函数尽可能的简单和愚蠢。这是因为构造函数中的错误处理可能是一个巨大的痛苦,因为析构函数没有被调用,返回一个耸人听闻的错误状态的唯一方法是抛出一个异常。
  • 这通常会破坏依赖反转原则,并可能越过demeter的线,并且通常会给代码带来很高的耦合。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27296421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档