0

したがって、2つのクラスがあります。1つは抽象クラスで、もう1つはそうではありません。

抽象クラスはIteratorであり、具象クラスはLinkedListIteratorです。両方のコードは投稿の下部にあります。

私が抱えている問題は、以下のコードにあります。デストラクタの最後の行にあるLinkedListIteratorで1つのエラーが発生します。

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

ここで、仮想の〜Iterator()デストラクタをコメントアウトしようとしましたが、エラーは発生しませんでしたが、次のような警告が表示されます。

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

だから私の質問は:抽象イテレータ基本クラスに仮想デストラクタが必要ですか?常に1つある必要があることを読みましたが、この場合、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に関するこのQ&Aも参照してください。

(*)リンクされたQ&Aで述べたように、純粋な仮想デストラクタ(定義はまだ必要です)を持つことは可能ですが、それは特に良いプログラミング手法ではありません。

于 2013-02-19T19:41:57.713 に答える
3

純粋であるかどうかに関係なく、仮想ベースデストラクタの定義を提供する必要があります。

virtual ~Iterator() { }

それを修正する必要があります。

PS:純粋に参考までにstdリンクリスト、std::listがあります

于 2013-02-19T19:41:33.620 に答える
3

デストラクタが純粋な仮想であるという事実にもかかわらず、型を使用できるようにするには、基本クラスに実装を提供する必要があります

Iterator;に空のデストラクタを追加するだけです。「純粋な」デストラクタを失う必要はありません(ただし、他の純粋な仮想メソッドがすでにあるため、あまり意味がありません)。

于 2013-02-19T19:42:00.770 に答える
2

他の人はあなたが見ているエラーを解決する方法に答えました、しかしあなたの質問

抽象Iterator基本クラスに仮想デストラクタが必要ですか?

回答されていません。

答えは、あなた(および他のユーザー)がこれらのクラスをどのように使用するかによって異なります。デストラクタがなくても問題はなく、誰かがポインタを介してインスタンスを決定するまでvirtual、すべてが正しく機能します。例えば:deleteLinkedListIteratorIterator

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

ただし、イテレータクラスを実装しているため、誰かがインスタンスを動的に割り当てる可能性はもちろん、多態的な削除を試みる可能性も最小限に抑える必要があります。ただし、すでに他の仮想関数を持っているので、デストラクタを宣言することの欠点も考えられませんvirtual

于 2013-02-19T20:05:04.410 に答える