面试题答案
一键面试函数调用实际情况及原因
- Base构造函数执行期间:
- 当进入
Derived
的构造函数,首先调用Base
的构造函数。此时,对象的类型被视为Base
类型。因为在Base
构造函数执行时,Derived
部分尚未初始化。 - 如果在
Base
构造函数中调用虚函数func()
(虽然题目是在Base
构造完成后调用,但先分析此情况便于理解),实际调用的是Base
类的func()
函数,而不是Derived
类重写的func()
函数。这是因为C++ 标准规定,在构造函数(包括析构函数)中调用虚函数,不会发生动态绑定,而是静态绑定到当前正在构造(或析构)的类的函数版本。
- 当进入
- Base构造完成后,Derived构造函数继续执行并调用func():
Base
构造完成后,Derived
部分开始初始化。当在Derived
构造函数中调用func()
时,由于对象已经部分构造完成(Base
部分已构造好),并且func()
是虚函数,此时会发生动态绑定。- 因为对象最终是
Derived
类型,所以实际调用的是Derived
类重写的func()
函数。
对程序设计的影响
- 潜在的未初始化问题:
- 如果
Derived
类的func()
函数依赖于Derived
类特有的成员变量,而这些成员变量在调用func()
时还未初始化(因为构造函数还在执行过程中),可能会导致程序出现未定义行为。例如,func()
可能访问一个未初始化的指针成员,导致程序崩溃。
- 如果
- 设计复杂度增加:
- 这种行为要求开发者对构造函数中虚函数调用格外小心,增加了程序设计和维护的复杂度。开发者需要清楚地知道在构造函数不同阶段调用虚函数的实际行为,以避免潜在的错误。
- 违背预期:
- 对于不熟悉C++ 构造函数中虚函数调用规则的开发者,可能会错误地认为在
Derived
构造函数中调用func()
一定会调用到Derived
类重写的版本,而忽略了在构造函数前期可能出现的特殊情况,从而引入难以调试的错误。
- 对于不熟悉C++ 构造函数中虚函数调用规则的开发者,可能会错误地认为在