2

我对何时以及为什么使用虚拟析构函数有些困惑。

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() 是虚拟的?
4

3 回答 3

4

1.) if ~Q()is virtual,~DQ()不管你写virtual不写都是虚拟的,所以两个析构函数都会被调用

2.) 调用delete p;是未定义的行为(可能只会调用Q' 的析构函数,但可能会崩溃或做任何事情,因为它是未定义的)。虚拟性是向下传播的,而不是向上传播的。

3.) 与#1 相同的情况,除了你明确写了virtual(顺便说一句,这是一个很好的做法)。两个析构函数都会被调用

于 2013-02-07T18:07:46.073 回答
2

我对何时以及为什么使用虚拟析构函数有些困惑。

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

我知道,如果我主要分配 aQ *p = new DQ();并删除 p,那么只会调用 Q 的析构函数。

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

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

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

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

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

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

那么一切都很好,您可以通过基类指针安全地删除对象。

于 2013-02-07T18:08:08.790 回答
1

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

于 2013-02-07T18:09:53.070 回答