Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我是否需要显式调用基本虚拟析构函数? 在C++中重写类(带有虚拟析构函数)时,我在继承类上再次实现析构函数,但需要调用基析构函数吗?< /p>_C++_Destructor - Fatal编程技术网

我是否需要显式调用基本虚拟析构函数? 在C++中重写类(带有虚拟析构函数)时,我在继承类上再次实现析构函数,但需要调用基析构函数吗?< /p>

我是否需要显式调用基本虚拟析构函数? 在C++中重写类(带有虚拟析构函数)时,我在继承类上再次实现析构函数,但需要调用基析构函数吗?< /p>,c++,destructor,C++,Destructor,如果是这样,我想是这样的 MyChildClass::~MyChildClass() // virtual in header { // Call to base destructor... this->MyBaseClass::~MyBaseClass(); // Some destructing specific to MyChildClass } 我说的对吗?不,您不需要调用基析构函数,派生析构函数总是为您调用基析构函数 要理解为什么要在基类中使用虚拟析构

如果是这样,我想是这样的

MyChildClass::~MyChildClass() // virtual in header
{
    // Call to base destructor...
    this->MyBaseClass::~MyBaseClass();

    // Some destructing specific to MyChildClass
}

我说的对吗?

不,您不需要调用基析构函数,派生析构函数总是为您调用基析构函数

要理解为什么要在基类中使用虚拟析构函数,请参阅下面的代码:

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


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

然后,如果B中没有虚拟析构函数,则只会调用~B()。但是,由于您有一个虚拟析构函数,因此将首先调用~D(),然后调用~B()。

否。它将自动调用。

否,析构函数将按与构造相反的顺序自动调用。(最后是基类)。不要调用基类析构函数。

其他人所说的,但也要注意,您不必在派生类中声明虚析构函数。一旦像在基类中一样声明了虚析构函数,所有派生的析构函数都将是虚的,无论您是否声明它们。换言之:

struct A {
   virtual ~A() {}
};

struct B : public A {
   virtual ~B() {}   // this is virtual
};

struct C : public A {
   ~C() {}          // this is virtual too
};

不可以。与其他虚拟方法不同,在虚拟方法中,您可以从派生方法显式调用基方法以“链”调用,编译器生成代码以按调用其构造函数的相反顺序调用析构函数

不,您从不调用基类析构函数,它总是像其他人指出的那样自动调用,但下面是概念证明和结果:

class base {
public:
    base()  { cout << __FUNCTION__ << endl; }
    ~base() { cout << __FUNCTION__ << endl; }
};

class derived : public base {
public:
    derived() { cout << __FUNCTION__ << endl; }
    ~derived() { cout << __FUNCTION__ << endl; } // adding call to base::~base() here results in double call to base destructor
};


int main()
{
    cout << "case 1, declared as local variable on stack" << endl << endl;
    {
        derived d1;
    }

    cout << endl << endl;

    cout << "case 2, created using new, assigned to derive class" << endl << endl;
    derived * d2 = new derived;
    delete d2;

    cout << endl << endl;

    cout << "case 3, created with new, assigned to base class" << endl << endl;
    base * d3 = new derived;
    delete d3;

    cout << endl;

    return 0;
}

如果将基类析构函数设为虚拟的,则实例3的结果将与情况1和2相同。C++中< < /P> < P>析构函数> C++ > <强> >仅当基类析构函数被声明为代码>虚< /代码> < /St>>时,自动得到调用< <强> >。 如果不是,则在删除对象时只调用基类析构函数

示例:没有虚拟析构函数

#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}
#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  //virtual destructor
  virtual ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
    delete(n);  //deleting the memory used by pointer
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}
示例:使用基本虚拟析构函数

#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}
#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  //virtual destructor
  virtual ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
    delete(n);  //deleting the memory used by pointer
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}
建议将基类析构函数声明为
virtual
,否则会导致未定义的行为


参考:

如果~B未声明为虚拟,该怎么办?~C仍然是虚拟的吗?是的。当一个虚方法(任何,而不仅仅是析构函数)被声明为虚时,派生类中该方法的所有重写都自动为虚。在这种情况下,即使您没有声明~B virtual,~C也是如此。但与基类中具有相同名称和相应方法参数的其他重写方法不同,析构函数名称不同。这有关系吗@boycy@YuanWen不,不会的,(一个且唯一)派生析构函数总是重写其基类的(一个且唯一)析构函数。那么纯虚拟析构函数呢?我的链接器试图在继承类的非虚拟析构函数末尾调用它;你不能有一个没有实体的纯虚拟析构函数。给它一个空的身体。对于常规的纯虚方法,会调用重写函数,而对于析构函数,它们都会被调用,因此必须提供一个主体。=0只是意味着它必须被重写,所以如果需要它,它仍然是一个有用的构造。这个问题可能是相关的,也有帮助。为什么Nick Bolton的代码不会导致分段错误,尽管它调用了两次基析构函数,对指向基类的指针调用两次
delete
,是否会导致分段错误?不能保证任何错误代码都会导致分段错误。此外,调用析构函数不会释放内存。请包含程序(伪)输出。它将帮助读者。@Kuldeepsingdhaka读者可以在现场看到它。很好的说明。如果您试图从派生类调用基类析构函数,您应该会得到类似于“错误:调用'base::base()'~base();”的匹配函数”的编译器错误,至少这是我的g++7.x编译器的行为。
#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  //virtual destructor
  virtual ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
    delete(n);  //deleting the memory used by pointer
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}
Base Constructor
Derived Constructor
Derived Destructor
Base Destructor