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