C++ 虚拟析构函数规则
我对何时以及为什么使用虚拟析构函数有点困惑C++ 虚拟析构函数规则,c++,memory,C++,Memory,我对何时以及为什么使用虚拟析构函数有点困惑 class Q { private: int i; int *pi; int *p; public: Q(int k); print(); ~Q() {delete pi; delete p;} }; class DQ : public Q { private: int *pd; public: DQ(); ~DQ(); }; 我明白,如果我主要分
class Q {
private:
int i;
int *pi;
int *p;
public:
Q(int k);
print();
~Q() {delete pi; delete p;}
};
class DQ : public Q
{
private:
int *pd;
public:
DQ();
~DQ();
};
我明白,如果我主要分配
Q *p = new DQ();
如果删除p,则只调用Q的析构函数
但在每一种情况下会发生什么:
~Q()
是虚拟的,~DQ()
是虚拟的,无论您是否编写虚拟的
,因此两个析构函数都将被调用
2.)调用删除p代码>是未定义的行为(可能只调用Q
的析构函数,但可能会崩溃或执行任意数量的操作,因为它是未定义的)。虚拟性向下传播,而不是向上传播
3.)与#1的情况相同,只是您明确地编写了virtual
(顺便说一句,这是一个很好的实践)。两个析构函数都将被调用
我对何时以及为什么使用虚拟析构函数有点困惑
class Q {
private:
int i;
int *pi;
int *p;
public:
Q(int k);
print();
~Q() {delete pi; delete p;}
};
class DQ : public Q
{
private:
int *pd;
public:
DQ();
~DQ();
};
为了以多态方式删除对象,需要在基类中使用虚拟析构函数;也就是说,通过指向基类型的指针删除派生类型的对象
我理解如果我主要分配一个Q*p=new DQ()
并删除p,则只调用Q的析构函数
不,你有未定义的行为。它可能会调用Q的析构函数,也可能会向你的老板发送一封侮辱性的电子邮件——第一封更可能,但原则上任何事情都可能发生
只有~Q()是虚拟的,~DQ()不是
那是不可能的。如果函数在类中是虚拟的,那么它在任何派生类中也是虚拟的
只有~DQ()是虚拟的,~Q()不是
然后,不允许通过指向Q
的指针删除类型为DQ
的对象;如果你尝试,你会得到未定义的行为。但是,如果您从DQ
派生另一个类,那么您可以通过指向DQ
(但不是Q
)的指针删除它们,这要归功于它的虚拟析构函数
~Q()是虚拟的,~DQ()是虚拟的
然后一切正常,您可以通过基类指针安全地删除对象。1.~DQ()和~Q()都是按照~DQ(),~Q()的顺序调用的。
2.只调用~Q()。
3.同时调用~DQ()和~Q()。virtual~Q()
意味着所有派生的析构函数都是虚拟的。所以(1)是没有意义的。我不能在不审查标准的情况下对(2)进行评论。(3)见(1)。一般来说,通过非多态指针触发基类销毁是非常困难的(或者上次我检查pre-C++11时是这样,我无法想象这会发生变化)。这里有一些提示:如果通过指向基类的指针删除派生类型的对象,则行为是未定义的。不需要调用Q
的析构函数。是否有任何原因导致否决票?我很肯定我的回答是正确的,但如果我错了,请告诉我。这对我来说也是个谜。此答案看起来正确且完整。对于2,由于基本析构函数不是虚拟的,因此这将仅调用派生的析构函数增益:行为未定义。这意味着没有要求。如果您想报告您所看到的特定编译器所做的事情,请务必这样做,但要将其标记为特定于实现的。