在构造和销毁期间调用虚拟方法会导致编译器错误?我听说这样做很危险。
我知道如果我有一个Class Base
定义虚拟方法的方法foo()
,那么 的解析在 的所有子类中foo()
都是动态Base
的。因此,如果子类Derived
覆盖foo()
thenDerived::foo()
被调用。那么为什么在构造/销毁期间调用虚方法会使编译器感到困惑呢?
从构造函数和外部调用它们有什么区别?
在构造和销毁期间调用虚拟方法会导致编译器错误?我听说这样做很危险。
我知道如果我有一个Class Base
定义虚拟方法的方法foo()
,那么 的解析在 的所有子类中foo()
都是动态Base
的。因此,如果子类Derived
覆盖foo()
thenDerived::foo()
被调用。那么为什么在构造/销毁期间调用虚方法会使编译器感到困惑呢?
从构造函数和外部调用它们有什么区别?
在构造过程中Base()
,派生类还没有被初始化,并且还没有真正存在。当您调用虚拟方法时,您的调用将转到Base::foo()
. 这不一定是错误的,但通常是出乎意料的,因此普遍禁止它。
同样在销毁过程中,Derived 在~Base()
被调用之前就被销毁了,所以再次调用虚拟方法会转到Base::foo()
,这又是经常出乎意料的。
尝试运行此示例:
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
对象)。同样的情况也发生在破坏中。