Итак, у меня есть два класса, один абстрактный, а другой нет.
Абстрактный класс — Iterator, а конкретный класс — LinkedListIterator. Код для обоих в нижней части поста.
У меня проблема с кодом, как показано ниже, я получаю 1 ошибку в LinkedListIterator
на последней строчке деструктора говорят
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;
}
Другие ответили, как решить ошибку, которую вы видите, но ваш вопрос
Нужен ли виртуальный деструктор в базовом классе абстрактных Итераторов?
не было ответа.
Ответ зависит от того, как вы (и другие пользователи) намереваетесь использовать эти классы. Нет ничего плохого в том, чтобы не иметь virtual
деструктор и все будет работать правильно до тех пор кто-то решает delete
экземпляр LinkedListIterator
через Iterator
указатель. Например:
Iterator<int> *iter = new LinkedListIterator<int>(...);
delete iter; // undefined behavior if Iterator destructor is not virtual
Но поскольку вы реализуете класс итераторов, шансы на то, что кто-то динамически выделит экземпляр, не говоря уже о попытке его полиморфного удаления, должны быть минимальными. Однако, поскольку у вас уже есть другие виртуальные функции, я не могу думать о недостатке объявления деструктора virtual
или.
Ваш базовый класс должен иметь virtual
деструктор, но не чистый virtual
деструктор (*).
Чистые виртуальные функции (то есть функции, помеченные как virtual
и с = 0
суффикс добавляется к их подписи) не имеют реализации. Однако деструктор базового класса всегда должен вызываться деструктором подкласса, и вы должны предоставить для него определение (возможно, пустое):
template<class T>
class Iterator {
public:
//~Constructors/Destructors------------//
/*
* Destroys necessary resources.
*/
virtual ~Iterator() { }
...
Также см этот вопрос&А на StackOverflow для связанной информации.
(*) Как уже упоминалось в связанном Q&О, возможно иметь чистый виртуальный деструктор (для которого определение все еще необходимо), но я не считаю это особенно хорошей практикой программирования.
Вы должны предоставить определение для вашего виртуального базового деструктора независимо от того, является ли он чистым.
virtual ~Iterator() { }
должен это исправить.
PS: чисто к вашему сведению есть список ссылок std, std :: list
Несмотря на то, что ваш деструктор чисто виртуальный, вы делать необходимо обеспечить реализацию в базовом классе, чтобы тип был пригодным для использования.
Просто добавьте пустой деструктор для Iterator
; вам не нужно терять «чистый» деструктор (хотя это не имеет особого смысла, поскольку у вас уже есть другие чисто виртуальные методы).