我们什么时候必须在派生类c ++中定义析构函数

时间:2015-01-19 22:55:08

标签: c++ destructor virtual-destructor

我是c ++的新手,我面临内存泄漏,这让我想知道我可能没有理解正确的事情。

我有:

.h文件

class DeliveryVehicle{
public:
    //c'tor
    DeliveryVehicle(const char* ID, Quality quality);

    //d'tor
    virtual ~DeliveryVehicle();

    ...
protected:
    VehicleParcelQueue parcelQueue_;
}

.c文件

DeliveryVehicle::~DeliveryVehicle(){
    while(!parcelQueue_.empty()) parcelQueue_.pop(); 
    // pop() calls removed element destructor
}

我有一个派生类,我依赖于默认的析构函数,而不是显式实现析构函数。

我想知道,如果我不使用" new"来在派生类中分配内存,那是否可以。

另外,我实现了自己的固定大小队列,它继承了STL的基类队列:

.h文件

class VehicleParcelQueue:public std::queue<Parcel*>{
public:
    const static int MaxParcelsNum = 5;
    Result push(Parcel*);
};

.cpp文件

typedef enum result{SUCCESS = 1,FAILURE = 0} Result;

Result VehicleParcelQueue::push(Parcel* pParcel){
if (size() >= 5) return FAILURE;
else{
    queue<Parcel*>::push(pParcel);
    return SUCCESS;
}

可以看出,在这种情况下,我没有明确地实现析构函数。 我是否容易发生内存泄漏?

也许pop不会为Parcle调用delete而是将析构函数调用指针? 谢谢

3 个答案:

答案 0 :(得分:4)

除了R Sahu的回答,请注意std::queue<>析构函数虚拟,从指针到Base的任何删除都会调用未定义的行为(因此,您通常不应该继承来自标准容器。)

您应该检查您的设计,例如使用类成员而不是继承,并在可能的情况下优先使用指针:

VehicleParcelQueue
{
    ...

    std::queue<Parcel> queue;
};

答案 1 :(得分:1)

当VehicleParcelQueue的实例超出范围时,将调用其析构函数,然后调用基类std :: queue的析构函数。 std :: queue的析构函数将是&#34; free&#34;队列的节点,但不会为存储在每个节点中的指针调用delete。您必须在VehicleParcelQueue的析构函数中手动执行此操作以避免泄漏。当然,如果某些其他对象仍然引用它们,您可能也不想删除这些对象。

  

也许pop不会为Parcle调用delete而是将析构函数调用指针?

正确。它从队列中删除节点,但不会在指针上调用delete。您必须获取节点的内容,即指针和调用删除。

答案 2 :(得分:0)

VehicleParcelQueue中的默认析构函数不会删除queue中指针指向的对象。这些是导致内存泄漏的对象。

<击> 您必须为VehicleParcelQueue实现析构函数,并确保删除Parcel中的所有queue个对象。

之前的建议不会起作用,因为queue的析构函数将首先被调用。

您最好的选择是使用

VehicleParcelQueue:public std::queue<std::unique_ptr<Parcel>>{

VehicleParcelQueue:public std::queue<std::shared_ptr<Parcel>>{