在构造和销毁期间调用虚方法会导致编译器错误?我听说做这件事很危险。
我知道如果我有Class Base
定义虚拟方法foo()
,foo()
的分辨率在{{1}的所有子类中都是动态 }}。因此,如果子类Base
覆盖Derived
,则调用foo()
。那么为什么在构造/销毁期间调用虚拟方法会让编译器感到困惑呢?
从构造函数和它之外调用它们有什么区别?
答案 0 :(得分:5)
在构造Base()
期间,派生类尚未初始化,并且尚未真正存在。当您拨打虚拟方法时,您的通话将转至Base::foo()
。这不一定是错的,但通常是意料之外的,因此一般禁止它。
同样在销毁期间,Derived在调用~Base()
之前被销毁,因此虚拟方法调用将再次转移到Base::foo()
,这通常也是意外的。
答案 1 :(得分:4)
尝试运行此示例:
struct base {
virtual int f() const { return 0; }
base() { std::cout << f() << "\n"; }
~base() { std::cout << f() << "\n"; }
};
struct derived : base {
const int value;
derived(int v) : value(v) {}
virtual int f() const { return value; }
};
derived d(100); // What should this print?
问题是当基类型的构造函数正在运行时,对象的类型仍为base
,而不是derived
。 Dispatch不会命中 final-overrider (从用户的角度来看,它只创建了一个derived
对象)。破坏也是如此。