【问题标题】:Omitting keyword virtual before destructor still works virtually在析构函数之前省略关键字 virtual 仍然有效
【发布时间】:2018-02-24 03:41:00
【问题描述】:
#include<iostream>
using namespace std;

class Mahesh
{

   public:
      Mahesh(){
         cout<<"Base Constructor is called at here"<<endl<<endl;
      }
      virtual ~ Mahesh()
      {
         cout<<"Base Destructor is called"<<endl<<endl;
      }
};

class Purnima:public Mahesh
{

   public:

      Purnima()
      {
         cout<<"Derived class constructor"<<endl<<endl;
      }
      ~Purnima(){
         cout<<"Derived class Destructor"<<endl<<endl;
      }
};

int main()
{
   Mahesh *m1;
   Purnima p1;
   m1=&p1;

   return 0;
}

我的问题是,如果我不在析构函数前面写关键字virtual,那么上面的代码就可以正常工作,那么为什么要使用虚拟析构函数呢?

【问题讨论】:

  • 重复都不合适。答案是virtual是继承的,不管你是否在派生的析构函数中重新指定。
  • 你甚至从不以多态方式调用析构函数。您实际上是在测试销毁派生类会调用父析构函数和派生析构函数。
  • 如果你写m1 = new Purnima; delete m1;,虚拟析构函数会有所不同
  • 在派生类中省略关键字没有区别:stackoverflow.com/questions/4895294/… 但在您的示例中,您甚至不需要在基类中使用 virtual。

标签: c++ virtual destructor


【解决方案1】:

当你这样写代码时

int main()
{
   Mahesh *m1;
   Purnima p1;
   m1=&p1;

   return 0;
}

当您超出范围时,您会自动销毁 Purnima p1。这就是您获得适当的析构函数序列调用的原因。

无论如何你不能删除m1,否则它会崩溃。

尝试将其封闭在范围内以更好地理解它。

int main()
{
   {
     Mahesh *m1;
     Purnima p1;
     m1=&p1;
   }
   cout<<"After Scope.."<<endl;

   return 0;
}

在析构函数调用后打印“After Scope”。

所以简而言之,在处理动态类型时需要virtual

【讨论】:

  • 当我想知道如果将 unique_ptr 分配为指向局部变量会发生什么时,我也有类似的想法。事实证明,它们并非完全防白痴。
【解决方案2】:

此代码中的任何内容都不需要虚拟析构函数,因此它确实可以正常工作。如果通过指向基类型的指针删除派生类型的对象,则需要虚拟析构函数。像这样:

Mahesh *m1 = new Purnima;
delete m1;

如果Mahesh 的析构函数不是虚拟的,则此代码具有未定义的行为。当心:未定义行为最隐蔽的表现之一是代码“工作正常”,直到您在其他地方进行轻微更改以准备向您最重要的客户进行演示,此时它将导致灾难性的失败。

【讨论】:

  • 您忘了提到,一旦问题变得明显,查找原因所需的时间与修复它的可用时间呈负相关。你拥有的时间越少,你需要的就越多。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-30
  • 2018-02-17
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 2014-01-30
相关资源
最近更新 更多