从调用析构虚函数(Calling virtual function from destructor)

2019-06-17 20:16发布

这安全吗?

class Derived:  public PublicBase, private PrivateBase
{
 ... 

   ~Derived()
   {
      FunctionCall();
   }

   virtual void FunctionCall()
   {
      PrivateBase::FunctionCall();
   }
}

class PublicBase
{
   virtual ~PublicBase(){};
   virtual void FunctionCall() = 0;
}

class PrivateBase
{
   virtual ~PrivateBase(){};
   virtual void FunctionCall()
   {
    ....
   }
}


PublicBase* ptrBase = new Derived();
delete ptrBase;

此代码与IP 有时 crases在一个错误的地址。

这不是一个好主意,呼吁构造一个虚拟函数是坦途。

从喜欢的文章http://www.artima.com/cppsource/nevercall.html我明白,析构函数也是一个不那么好地方调用虚函数。

我的问题是:“这是真的吗?” 我曾与VS2010和VS2005测试,PrivateBase :: FunctionCall被调用。 未定义行为?

Answer 1:

我要去对这里的流量......但是首先,我必须假设你PublicBase析构函数是虚拟的,因为否则Derived的析构函数永远不会被调用。

它通常不是一个好主意,叫从构造函数/析构虚函数

这样做的原因是,动态调度是在这两个操作奇怪。 对象的实际类型在施工期间发生变化 ,但破坏过程中再次发生变化 。 当正在执行的析构函数,对象正是型的,并且不会从它派生的类型。 动态分配是在所有的时间效应,但虚拟函数的最终置换器将根据在哪里,你是层次改变。

也就是说,你不应该指望一个虚函数调用在构造函数/析构函数中的任何类型的从构造函数/析构函数中正在执行的类型派生执行。

在您的特定情况下, 最终置换器(至少在层次结构的这一部分) 高于你的水平。 此外, 不使用动态分配的。 呼叫PrivateBase::FunctionCall(); 是静态解析,并有效地等同于任何非虚函数调用。 事实上,该功能是虚拟的还是不不会影响这一呼吁。

所以, 是的,它是做精,你在做什么,虽然你将被迫为大多数人了解规则的口头禅,而不是它的原因来解释这个在代码审查。



Answer 2:

这安全吗?

是。 呼叫从一个构造或析构一个虚函数调度功能仿佛对象的动态类型是当前正在建造或破坏。 在这种情况下,它是从的析构函数称为Derived ,所以它派往Derived::FunctionCall (在你的情况下,调用PrivateBase::FunctionCall非虚拟)。 所有这一切都被很好地定义。

这“不是一个好主意”来调用构造函数和析构函数虚函数的原因有三:

  • 这会导致意外的行为,如果你从一个基类调用它,(错误地)希望它被分派到在派生类中的覆盖;
  • 这将导致未定义的行为,如果是纯虚拟的;
  • 你会一直有解释你的人谁相信,它总是错误的决定。


Answer 3:

在一般情况下,这不是一个好主意,调用虚函数,除非它可能会派往类的对象(即最派生类的“全”对象)完全构造。 这是不是这样的

  • 直到所有构造函数完成执行
  • 任何析构函数执行完毕后,


Answer 4:

它是根据斯科特非常糟糕的主意: 链接

这是我已经编译和运行,以帮助自己更好地理解销毁过程中,你可能还会发现它有用

#include <iostream>
using namespace std;


class A {
public:
  virtual void method() {
    cout << "A::method" << endl;
  }

  void otherMethod() {
    method();
  }

  virtual ~A() {
    cout << "A::destructor" << endl;
    otherMethod();
  }

};

class B : public A {
public:
  virtual void method() {
    cout << "B::method" << endl;
  }

  virtual ~B() {
    cout << "B::destructor" << endl;
  }
};

int main() {

  A* a = new B();

  a->method();

  delete a;

}


文章来源: Calling virtual function from destructor
标签: c++ virtual