[英]Do I still need to have a virtual destructor for my derived class in this situation?
[英]I have a virtual destructor and an array in my base class. How can I make it work?
例如:
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?
}
我的基类中有一个虚拟析构函数和一个数组。 如果基类析构函数被派生类析构函数覆盖,则基数组将不会被删除。 有什么好的解决方案?
基类的析构函数被自动调用,派生类的析构函数运行之后。
当销毁派生对象并且基部的析构函数是虚拟的时,两个析构函数都将被调用。 您可以在这里确认: http : //ideone.com/RZamr
该顺序将与构造函数的顺序相反,即,在构造时,将首先调用base
的构造函数,然后再调用derived
。 首先销毁时将调用derived
的析构函数,然后调用base
。
虚拟析构函数的工作方式不同于其他虚拟函数,因为基类的虚拟析构函数永远不会被覆盖。 相反,当子类提供自己的析构函数时,该子类析构函数将触发,然后基类析构函数也会触发。 使用“虚拟”是为了使您通过基类指针删除派生类对象,C ++会根据对象的动态类型(子类)而不是静态类型的指针(子类)来调用析构函数。超类)。 因此,您不需要在这里做任何特别的事情。 基类析构函数将照常工作。
希望这可以帮助!
覆盖析构函数时,只要定义为“虚拟”,就仍会调用基类的析构函数。
因此,在此示例中:
class base
{
public:
base()
{
myarray = new float[100];
}
~base()
{
delete[] myarray;
}
private:
float* myarray;
}
class derived : public base
{
public:
derived()
{
}
~derived()
{
}
}
这不会删除'myarray'并且会泄漏内存,因为基类析构函数被派生类析构函数隐藏。 然而:
class base
{
public:
base()
{
myarray = new float[100];
}
virtual ~base()
{
delete[] myarray;
}
private:
float* myarray;
}
class derived : public base
{
public:
derived()
{
}
~derived()
{
}
}
这将删除阵列。
请记住,构造函数是从基类开始调用的,因此首先调用基类的构造函数,然后再调用派生类,而析构函数的调用顺序相反,因此,派生类的析构函数先于基类调用。
没问题 在派生类析构函数被调用之后立即调用基类析构函数。
仅有一种情况是不正确的:在指向基类析构函数不是虚拟的基类的指针上调用delete。
在所有具有在堆栈上创建的类的本地实例且函数或方法退出的情况下,即使由于异常,实例也会被正确地销毁。
在所有情况下,如果类的实例是new
d,随后又通过指向实例化的确切类的指针删除了该实例,则该实例将被正确地销毁。
当一个类的实例是new
d,但通过基类指针删除时,只有在基类具有虚拟析构函数(声明的virtual
本身或其自身的基具有虚拟析构函数)时,该实例才被正确地破坏。正确地破坏了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.