删除抽象非虚拟dtor c ++

delete abstract non virtual dtor c++

我有一个表示抽象数据类型的接口 'Bag'。为了实现该抽象数据类型,我使用了基于数组和基于链接的实现。

这里定义class

edit 如您所指,我已将虚拟析构函数添加到我的 Base class

template<class ItemType>
class BagInterface{

public:
    virtual int getCurrentSize() const = 0;
    
    virtual bool isEmpty() const = 0;
    
    virtual bool add(const ItemType& newEntry) = 0;
    
    virtual bool remove(const ItemType& anEntry) = 0;
    
    virtual int getFrequencyOf(const ItemType& anEntry) const = 0;
    
    virtual bool contains (const ItemType& anEntry) const = 0;

    virtual void clear() = 0;
    
    virtual vector<ItemType> toVector() const = 0;

    virtual ~BagInterface() = default;
};


#endif /* BagInterface_hpp */

我的 2 个派生 class 在途中实现了这些方法。

我的基于 link 的实现使用虚拟析构函数,因为与基于数组的实现不同,它动态分配内存,最终它必须使用 'delete' 关键字删除实例以避免内存泄漏。

linked 包的析构函数

template<class ItemType>
LinkedBag<ItemType>::~LinkedBag(){
    clear(); // Clears bag's content.
}

arraybag 的析构函数

template<class ItemType>
ArrayBag<ItemType>::~ArrayBag(){
    clear();
}

在所有实施问题之后,我想测试我的 ADT 操作。

我创建了一个函数,它将指针作为输入来表示包。

void bagTester(BagInterface<int>* bagPtr){
   // do some test }

在我的主要功能中,在我完成测试后我想删除我的 bagPtr 因为我已经完成了它所以是时候删除它了。

  int main(){
     BagInterface<int>* bagPtr = nullptr;
    
     char userChoice;
     cin>> userChoice;
    
     if(userChoice == 'A'){
     bagPtr = new ArrayBag<int>(); // Array based implementation 
    }else if(userChoice == 'L'){
     bagPtr = new LinkedBag<int>(); // Link bases implementation
    }

    bagTester(bagPtr); // test my bag
    
    delete bagPtr; // and now i'm finished with test let's delete the pointer
    bagPtr = nullptr; // deallocate
}

**在那一点上我的错误发生了,编译器给出了警告 -> **

In file included from main.cpp:2:
In file included from ./LinkedBag.hpp:5:
./BagInterface.hpp:36:31: warning: defaulted function definitions are a C++11 extension [-Wc++11-extensions]
    virtual ~BagInterface() = default;
                              ^
In file included from main.cpp:4:
./ArrayBag.hpp:28:5: error: exception specification of overriding function is more lax than base version
    ~ArrayBag();
    ^
main.cpp:48:22: note: in instantiation of template class 'ArrayBag<int>' requested here
        bagPtr = new ArrayBag<int>();
                     ^
./BagInterface.hpp:36:13: note: overridden virtual function is here
    virtual ~BagInterface() = default;
            ^
In file included from main.cpp:2:
./LinkedBag.hpp:25:1: error: exception specification of overriding function is more lax than base version
~LinkedBag();
^
main.cpp:52:22: note: in instantiation of template class 'LinkedBag<int>' requested here
        bagPtr = new LinkedBag<int>();
                     ^
./BagInterface.hpp:36:13: note: overridden virtual function is here
    virtual ~BagInterface() = default;
            ^
1 warning and 2 errors generated.

我查看了这个相关主题 ->

我尝试了其中一项建议,即:

Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.

并且还尝试将虚拟析构函数添加到 BagInterface,但没有成功。(编辑:我了解到我应该添加虚拟析构函数 :))

我不明白这个问题,因为两个派生 class 都有自己的析构函数,arrayBag 有默认析构函数,linkedBag 有虚拟析构函数。

那么,我怎样才能避免警告呢?

现在,当您 运行 此代码时:

delete bagPtr;

未调用基于 link 的实现的析构函数。

template<class ItemType>
class BagInterface{

public:
.....
virtual ~BagInterface() = default;
};

如果您要通过指向 BagInterface 的指针删除从 BagInterface 派生的 class(或者如果 sharedpointer<BagInterface> 指向从 BagInterface 派生的 class超出范围)。

My link based implementation is using virtual destructor because unlike array based implementation it's dynamically allocating memory and eventually it has to delete instance by using 'delete' keyword due to avoid from memory leaks.

这就是为什么您需要在基 class 中使用虚拟析构函数:如果没有,当您通过基 [=23= 的指针删除派生 class 时],你会得到未定义的行为。

Deleting an object through pointer to base invokes undefined behavior unless the destructor in the base class is virtual. source here