0

所以我有两个类,一个是抽象的,一个不是。

抽象类是Iterator,具体类是LinkedListIterator。两者的代码都在帖子的底部。

我遇到的问题是代码如下,我在析构函数的最后一行的 LinkedListIterator 中出现 1 个错误说

undefined reference to `Iterator<int>::~Iterator()'

现在我尝试注释掉虚拟 ~Iterator() 析构函数,没有错误,但我收到警告说:

Class '[C@800c1' has virtual method 'remove' but non-virtual destructor

所以我的问题是:抽象迭代器基类中是否需要一个虚拟析构函数?我读过你应该总是有一个,但在这种情况下,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;
        }
4

4 回答 4

6

您的基类应该有一个virtual析构函数,但不是 virtual析构函数 (*)。

纯虚函数(即标记为virtual并在= 0其签名后附加后缀的函数)没有实现。然而,基类的析构函数总是需要被子类的析构函数调用,你应该为它提供一个定义(可能是一个空的):

template<class T>
class Iterator {

    public:
        //~Constructors/Destructors------------//
        /*
         * Destroys necessary resources.
         */
        virtual ~Iterator() { }
    ...

另请参阅StackOverflow 上的此问答以获取相关信息。

(*) 如链接的问答中所述,可以有一个纯虚拟析构函数(仍然需要定义),但我认为这不是一个特别好的编程实践。

于 2013-02-19T19:41:57.713 回答
3

您需要为您的虚拟基础析构函数提供定义,无论它是否是纯析构函数。

virtual ~Iterator() { }

应该修复它。

PS:仅供参考,有一个标准链接列表,std::list

于 2013-02-19T19:41:33.620 回答
3

尽管您的析构函数是纯虚拟的,但您确实需要在基类中提供一个实现以使该类型可用。

Iterator只需为;添加一个空的析构函数 您不需要丢失“纯”析构函数(尽管它没有多大意义,因为您已经拥有其他纯虚方法)。

于 2013-02-19T19:42:00.770 回答
2

其他人已经回答了如何解决您看到的错误,但是您的问题

我需要抽象迭代器基类中的虚拟析构函数吗?

尚未得到答复。

答案是这取决于您(和其他用户)打算如何使用这些类。没有virtual析构函数并没有错,一切都会正常工作,直到有人决定通过指针delete的实例。例如:LinkedListIteratorIterator

Iterator<int> *iter = new LinkedListIterator<int>(...);
delete iter; // undefined behavior if Iterator destructor is not virtual

但是,由于您正在实现一个迭代器类,因此动态分配实例的可能性应该很小,更不用说尝试对其进行多态删除了。但是,由于您已经拥有其他虚函数,因此我也想不出声明析构函数的缺点virtual

于 2013-02-19T20:05:04.410 回答