C++ 中的黄金法则之一是实例的生命周期从其构造函数成功完成时开始,并在其析构函数开始时结束。
根据这条规则,我们得出结论,在构造函数中调用虚方法不是一个好主意,因为可能的派生实例无效,这将导致未定义的行为。
C++ FAQ 20.8中提到的 Virtual Constructor Idiom似乎表明相反的情况。
我的问题是:
- 标准中定义对象相对于构造函数和析构函数调用的生命周期的确切定义是什么?
- 此外,所谓的“Virtual Constructor Idom”是否有效?
C++ 中的黄金法则之一是实例的生命周期从其构造函数成功完成时开始,并在其析构函数开始时结束。
根据这条规则,我们得出结论,在构造函数中调用虚方法不是一个好主意,因为可能的派生实例无效,这将导致未定义的行为。
C++ FAQ 20.8中提到的 Virtual Constructor Idiom似乎表明相反的情况。
我的问题是:
我认为您混淆了两个独立的(如果相关的)事物。
当构造函数启动时,对象作为构造函数所属的类的类型存在,该对象可能处于不一致的状态(这很好,因为当前执行在对象的方法之一内)。也就是说,实际上继承自 Base 的 Derived 类型的对象在 Base 构造函数中被视为 Base;this
in anyBase::Base()
被视为 a Base *
,无论this
指向的对象的实际类型如何。调用虚方法很好。在构造函数中,将调用构造函数类的虚方法,而不是对象的实际类型。
您的第一个问题在“派生类复制构造函数的初始化列表中的基类”中进行了介绍。简短的回答是 C++03 的 § 12.7 2-3 涵盖了它。
虚拟构造函数成语是完全有效的。