虚拟析构函数规则

时间:2013-02-07 17:45:52

标签: 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(); 
};

据我所知,如果主要是我分配了一个

Q *p = new DQ();

并删除p,然后只调用Q的析构函数。

但是每种情况都会发生什么:

  1. 只有~Q()是虚拟的而~DQ()不是?
  2. 只有~DQ()是虚拟的,而~Q()不是?
  3. ~Q()是虚拟的,~DQ()是虚拟的吗?

3 个答案:

答案 0 :(得分:4)

1。)如果~Q()是虚拟的,~DQ()是虚拟的,无论你是否写virtual,所以两个析构函数都将被调用

2。)调用delete p;是未定义的行为(可能只会调用Q的析构函数,但可能会崩溃或执行任何数量的操作,因为它未定义)。虚拟传播向下传播,而不是传播。

3。)与#1相同的情况除了你明确地写了virtual(顺便说一句,这是一个好习惯)。两个析构函数都将被称为

答案 1 :(得分:2)

  

我对使用虚拟析构函数的时间和原因感到困惑。

您需要在基类中使用虚拟析构函数才能以多态方式删除对象;也就是说,通过指向基类型的指针删除派生类型的对象。

  

据我所知,如果在main中我分配一个Q *p = new DQ();并删除p,那么只调用Q的析构函数。

不,你得到未定义的行为。它可能会调用Q的析构函数,或者它可能会向您的老板发送一封侮辱性的电子邮件 - 第一个更有可能,但原则上任何事情都可能发生。

  

只有~Q()是虚拟的而~DQ()不是?

那是不可能的。如果一个函数在一个类中是虚函数,那么它在任何派生类中也是虚函数。

  

只有~DQ()是虚拟的,而~Q()不是?

然后,您不能通过指向DQ的指针删除Q类型的对象;如果你尝试,你会得到未定义的行为。但是,如果从DQ派生另一个类,那么由于其虚拟析构函数,您可以通过指向DQ(但 Q)的指针删除它们。

  

~Q()是虚拟的,〜DQ()是虚拟的吗?

然后一切都很好,你可以通过基类指针安全地删除对象。

答案 2 :(得分:1)

1.~DQ()和~Q()按~DQ(),~Q()的顺序调用。 2.只调用~Q()。 3.Both~DQ()和~Q()被调用。