1

在构造和销毁期间调用虚拟方法会导致编译器错误?我听说这样做很危险。

我知道如果我有一个Class Base定义虚拟方法的方法foo(),那么 的解析在 的所有子类中foo()都是动态Base的。因此,如果子类Derived覆盖foo()thenDerived::foo()被调用。那么为什么在构造/销毁期间调用虚方法会使编译器感到困惑呢?

从构造函数和外部调用它们有什么区别?

4

2 回答 2

6

在构造过程中Base(),派生类还没有被初始化,并且还没有真正存在。当您调用虚拟方法时,您的调用将转到Base::foo(). 这不一定是错误的,但通常是出乎意料的,因此普遍禁止它。

同样在销毁过程中,Derived 在~Base()被调用之前就被销毁了,所以再次调用虚拟方法会转到Base::foo(),这又是经常出乎意料的。

于 2012-11-19T18:37:17.577 回答
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对象)。同样的情况也发生在破坏中。

于 2012-11-19T18:39:35.267 回答