C++中的继承和虚拟析构函数问题
Issue with inheritance and virtual destructors in C++
所以我有两个类,一个是抽象的,一个不是。
抽象类是Iterator,具体类是LinkedListIterator。两者的代码都在帖子的底部。
我遇到的问题是下面的代码,我在LinkedListIterator中得到了1个错误在析构函数的最后一行说
undefined reference to `Iterator<int>::~Iterator()'
现在我试着注释掉虚拟的~Iterator()析构函数,没有错误,但我得到了一个警告:
Class '[C@800c1' has virtual method 'remove' but non-virtual destructor
所以我的问题是:在抽象的Iterator基类中,我需要一个虚拟析构函数吗?我读到过应该总是有一个,但在这种情况下,LinkedListIterator中的析构函数只是设置值,它不会释放任何东西。。。
谢谢!
迭代程序代码:
template<class T>
class Iterator {
public:
//~Constructors/Destructors------------//
/*
* Destroys necessary resources.
*/
virtual ~Iterator() = 0;
//~Methods-------------------//
/*
* Informs the user whether there are more elements to be iterated
* over in a List.
*
* @return true if there are more elements to iterate over, false otherwise.
*/
virtual bool hasNext() = 0;
/*
* Gets the next element to iterate over.
*
* @return the next element in the iteration.
*/
virtual T next() = 0;
/*
* Adds an element to the List being iterated over.
*
* @param element the element to add.
* @return true if successful, false otherwise.
*/
virtual bool add(T element) = 0;
/*
* Removes the element last returned by next from
* the List being iterated over.
*
* @return true if successful, false otherwise.
*/
virtual bool remove() = 0;
};
相关的LinkedListIterator代码(它是一个较长的类):
template<class T>
class LinkedListIterator : public Iterator<T> {
private:
//~Data Fields---------------------------------//
/*
* Pointer to the node that the iterator is currently at.
*/
Node<T>* current;
/*
* Pointer to the LinkedList being iterated through.
*/
LinkedList<T>* list;
/*
* Boolean value indicating whether next has been called since
* the last remove operation.
*/
bool nextCalled;
public:
//~Constructors/Destructors------------------//
/*
* Constructor for LinkedListIterator, takes in a pointer to a Node
* to initialize current to point to (intended to be the head of the
* the LinkedList).
*
* @param theList pointer to the LinkedList being iterated through.
*/
LinkedListIterator(LinkedList<T>* theList) {
current = theList->head;
list = theList;
nextCalled = false;
}
/*
* Destructor, resets pointer values to 0.
*/
~LinkedListIterator() {
current = 0;
list = 0;
}
基类应该有一个virtual
析构函数,但不能有一个纯virtual
析构函数(*)。
纯虚拟函数(即标记为virtual
并在其签名后附加= 0
后缀的函数)没有实现。然而,基类的析构函数总是需要由子类的析构因子调用,并且您应该为它提供一个定义(可能是空的):
template<class T>
class Iterator {
public:
//~Constructors/Destructors------------//
/*
* Destroys necessary resources.
*/
virtual ~Iterator() { }
...
另请参阅此问答;有关相关信息,请参见StackOverflow上的A。
(*)如链接问答中所述;A、 有可能有一个纯粹的虚拟析构函数(对它来说,定义仍然是必要的),但我认为这不是一个特别好的编程实践。
无论虚拟基析构函数是否为纯析构函数,都需要为其提供一个定义。
virtual ~Iterator() { }
应该修复它。
PS:仅供参考,这里有一个std链接列表,std::list
尽管析构函数是纯虚拟的,但确实需要在基类中提供一个实现,使类型可用。
只需为Iterator
添加一个空的析构函数;您不需要丢失"纯"析构函数(尽管它没有多大意义,因为您已经有了其他纯虚拟方法)。
其他人已经回答了如何解决您看到的错误,但您的问题
在抽象Iterator基类中需要虚拟析构函数吗?
尚未得到答复。
答案是,这取决于您(和其他用户)打算如何使用这些类。没有virtual
析构函数没有错,一切都会正常工作,直到有人决定通过Iterator
指针将LinkedListIterator
的实例delete
。例如:
Iterator<int> *iter = new LinkedListIterator<int>(...);
delete iter; // undefined behavior if Iterator destructor is not virtual
但是,由于您正在实现迭代器类,因此有人动态分配实例的可能性应该很小,更不用说尝试对其进行多态删除了。然而,由于您已经有了其他虚拟函数,我想不出声明析构函数virtual
有什么缺点。
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 是否可以使用函数指针调用虚拟析构函数?
- 在没有动态内存的世界中,我是否需要虚拟析构函数?
- 程序永远不会进入虚拟析构函数
- C++ std::vector 中的虚拟析构函数继承
- 哪种方法更适合处理虚拟析构函数?
- 拥有"受保护的非虚拟析构函数"与"受保护虚拟析构构函数"有什么好处
- 带有未解析外部元素的C++虚拟析构函数
- 即使基类和派生类只使用基元数据类型,我是否需要定义虚拟析构函数
- C++切片和虚拟析构函数
- C++虚拟继承、虚拟析构函数和 dynamic_cast<void*>
- 添加虚拟析构函数会使代码大小膨胀
- 应该是虚拟析构函数吗?但是怎么做呢?
- 虚拟析构函数将对象移出 rodata 部分
- 如何将 std::unique_ptr<Parent> 与具有受保护虚拟析构函数的只读父类一起使用
- DIRECTX9 中自定义顶点的虚拟析构函数
- 为什么缺少虚拟析构函数不会导致内存泄漏?
- std::unique_ptr 在虚拟析构函数上重置 SIGABRT
- C++11 中默认纯虚拟析构函数的正确放置
- 在派生类中重写哪个基类的虚拟析构函数