面试题答案
一键面试多态机制在这种情况下的工作原理
在C++ 中,当在Derived
类的构造函数中调用Base
类的虚函数时,由于对象在构造期间,其类型还未完全构建完成。此时,对象的动态类型是Base
类类型(因为Base
类的构造函数正在执行),而不是Derived
类类型。所以,调用的是Base
类版本的虚函数,而不是Derived
类重写的版本,多态机制在此处不会按照预期(基于Derived
类类型)工作。
潜在风险
- 逻辑错误:如果程序员期望调用
Derived
类重写的虚函数来完成某些特定的初始化工作,但实际调用的是Base
类版本,可能导致初始化不完整或不正确,从而引发运行时逻辑错误。 - 代码维护困难:这种调用方式违背了多态的常规预期,使得代码的行为难以理解和调试,增加了维护成本。
改进建议
- 避免在构造函数中调用虚函数:将需要在构造函数中执行的虚函数相关操作,提取到一个单独的非构造函数(例如
init
函数)中,在构造完成后显式调用该函数。
class Base {
public:
virtual void virtualFunction() {
// Base类实现
}
};
class Derived : public Base {
public:
Derived() {
// 不在这里调用虚函数
}
void init() {
virtualFunction();
}
void virtualFunction() override {
// Derived类实现
}
};
- 使用模板方法模式:在
Base
类构造函数中调用一个非虚的模板方法,该模板方法调用虚函数。在Derived
类中重写虚函数,而不是在构造函数中直接调用虚函数。
class Base {
public:
Base() {
init();
}
private:
void init() {
virtualFunction();
}
virtual void virtualFunction() {
// Base类实现
}
};
class Derived : public Base {
public:
void virtualFunction() override {
// Derived类实现
}
};
这样,通过模板方法模式,在Base
类构造函数执行时,虽然调用的是Base
类的虚函数版本,但在Derived
类中可以通过重写虚函数来提供特定实现,同时避免了在Derived
类构造函数中直接调用虚函数的问题。