Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/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++ 我的基类中有一个虚拟析构函数和一个数组。我怎样才能让它工作?_C++_Virtual Destructor - Fatal编程技术网

C++ 我的基类中有一个虚拟析构函数和一个数组。我怎样才能让它工作?

C++ 我的基类中有一个虚拟析构函数和一个数组。我怎样才能让它工作?,c++,virtual-destructor,C++,Virtual Destructor,例: 我的基类中有一个虚拟析构函数和一个数组。如果基类析构函数被派生类析构函数重写,则不会删除basearray。什么是好的解决方案?基类析构函数在派生类析构函数运行之后自动调用。基类析构函数自动调用,就在派生类析构函数运行之后。当析构函数是派生对象且基的析构函数是虚拟的时,两个析构函数都将被调用。您可以在此处确认: 该顺序将与构造函数的顺序相反,即在首先构造base的构造函数时,将调用派生的的构造函数。首先销毁时,将调用派生的析构函数,然后调用基的析构函数。当销毁派生对象且基的析构函数为虚拟时

例:


我的基类中有一个虚拟析构函数和一个数组。如果基类析构函数被派生类析构函数重写,则不会删除basearray。什么是好的解决方案?

基类析构函数在派生类析构函数运行之后自动调用。

基类析构函数自动调用,就在派生类析构函数运行之后。

当析构函数是派生对象且基的析构函数是虚拟的时,两个析构函数都将被调用。您可以在此处确认:


该顺序将与构造函数的顺序相反,即在首先构造
base
的构造函数时,将调用
派生的
的构造函数。首先销毁时,将调用
派生
的析构函数,然后调用
的析构函数。当销毁派生对象且基的析构函数为虚拟时,将调用两个析构函数。您可以在此处确认:


该顺序将与构造函数的顺序相反,即在首先构造
base
的构造函数时,将调用
派生的
的构造函数。首先进行析构函数时,将调用
派生的
的析构函数,然后调用
中的一个

虚拟析构函数的工作方式与其他虚拟函数的工作方式不同,因为基类的虚拟析构函数从不被重写。相反,当一个子类提供自己的析构函数时,该子类析构函数激发,然后基类析构函数也激发。这里使用的是“虚拟”,这样如果通过基类指针删除派生类对象,C++就知道根据对象的动态类型(子类)调用析构函数,而不是指针的静态类型(超类)。因此,您不需要在这里做任何特殊的事情。基类析构函数将正常工作


希望这有帮助

虚拟析构函数的工作方式与其他虚拟函数不同,因为基类的虚拟析构函数永远不会被重写。相反,当一个子类提供自己的析构函数时,该子类析构函数激发,然后基类析构函数也激发。这里使用的是“虚拟”,这样如果通过基类指针删除派生类对象,C++就知道根据对象的动态类型(子类)调用析构函数,而不是指针的静态类型(超类)。因此,您不需要在这里做任何特殊的事情。基类析构函数将正常工作


希望这有帮助

重写析构函数时,基类析构函数仍然被调用,只要它被定义为“virtual”,这就是您所做的

所以在这个例子中:

class base
{
public:
  base()
  {
    // allocate memory for basearray
  }
  virtual ~base()
  {
    // delete basearray
  }

protected:
  float* basearray;
};

class derived1 : public base
{
public:
  derived1()
  {
    // allocate memory for derivedarray
  }
  ~derived1()
  {
    // delete derived array
  }

protect:
  float* derivedarray;
};

void main()
{
  derived1 d;

  ...

  base* pb = &d;

  ...

  // Delete base array? 
}
这不会删除“myarray”,并且会泄漏内存,因为基类析构函数被派生类析构函数隐藏。然而:

  class base
  {
  public:
     base()
     {
        myarray = new float[100];
     }

     ~base()
     {
        delete[] myarray;
     }

  private:
     float* myarray;
  }


  class derived : public base
  {
  public:
     derived()
     {
     }

     ~derived()
     {
     }
  }
这将删除该数组


请记住,构造函数是从基类开始调用的,因此首先调用基类构造函数,然后调用派生类,而析构函数的调用顺序相反,因此,在调用基类析构函数之前,会先调用派生类析构函数。

重写析构函数时,基类析构函数仍然会被调用,只要它被定义为“virtual”,这就是您所做的

所以在这个例子中:

class base
{
public:
  base()
  {
    // allocate memory for basearray
  }
  virtual ~base()
  {
    // delete basearray
  }

protected:
  float* basearray;
};

class derived1 : public base
{
public:
  derived1()
  {
    // allocate memory for derivedarray
  }
  ~derived1()
  {
    // delete derived array
  }

protect:
  float* derivedarray;
};

void main()
{
  derived1 d;

  ...

  base* pb = &d;

  ...

  // Delete base array? 
}
这不会删除“myarray”,并且会泄漏内存,因为基类析构函数被派生类析构函数隐藏。然而:

  class base
  {
  public:
     base()
     {
        myarray = new float[100];
     }

     ~base()
     {
        delete[] myarray;
     }

  private:
     float* myarray;
  }


  class derived : public base
  {
  public:
     derived()
     {
     }

     ~derived()
     {
     }
  }
这将删除该数组


请记住,构造函数是从基类开始调用的,因此首先调用基类构造函数,然后调用派生类,而析构函数是按相反顺序调用的,因此在调用基类析构函数之前调用派生类析构函数。

这里没有问题。在调用派生类析构函数之后立即调用基类析构函数

只有一种情况是不正确的:对指向基类析构函数不是虚拟的基类的指针调用delete

在所有情况下,如果您拥有在堆栈上创建的类的本地实例,并且函数或方法退出,即使是因为异常,实例也会正确地被销毁

在所有情况下,如果一个类的实例是
new
d,然后通过指向实例化的确切类的指针删除,则该实例将被正确地销毁


当一个类的实例是
new
d,但通过基类指针删除时,只有当基类有一个虚拟析构函数(声明的
virtual
本身或它自己的基类有一个虚拟析构函数)时,该实例才被正确析构函数。

这里没有问题。在调用派生类析构函数之后立即调用基类析构函数

只有一种情况是不正确的:对指向基类析构函数不是虚拟的基类的指针调用delete

在所有情况下,如果您拥有在堆栈上创建的类的本地实例,并且函数或方法退出,即使是因为异常,实例也会正确地被销毁

在所有情况下,如果一个类的实例是
new
d,然后通过指向实例化的确切类的指针删除,则该实例将被正确地销毁


当一个类的实例是
new
d,但通过基类指针删除时,只有当基类有一个虚拟析构函数(声明的
virtual
本身或它自己的基类有一个虚拟析构函数)时,该实例才被正确析构函数。

您应该能够调用parent