Перед созданием функций, которые возвращают Stack<T>
по значению, или имеют функции, которые требуют семантики копирования для Stack<T>
(как в operator +
), необходимо убедиться, что Stack<T>
безопасно для копирования.В данный момент вам не хватает конструктора копирования, поэтому ваш operator +
никогда не будет работать правильно, даже если сама функция не содержит ошибок.
Вам не хватает этой функции:
Stack::Stack(const Stack<T>&)
Самый простой способ реализовать конструктор копирования - это извлечь большую часть кода из оператора присваивания и поместить его в конструктор копирования.Более или менее, код должен выглядеть примерно так (код не был скомпилирован или протестирован - он иллюстрирует основной смысл этого ответа):
template <typename T>
Stack<T>::Stack<T>(const Stack<T> &stack_obj) : top(nullptr), size(0)
{
Node *tmp;
Node *ptr;
Node *last;
Node *new_node;
ptr = stack_obj.top;
while (ptr)
{
new_node = new Node;
new_node->data = ptr->data;
new_node->next = nullptr;
if (!top)
{
top = new_node;
last = new_node;
}
else
{
last->next = new_node;
last = new_node;
}
ptr = ptr->next;
}
}
Вы уже написали деструкторэто должно сработать, поэтому мы не будем вдаваться в эту функцию, но для следующего шага необходим рабочий деструктор - реализация оператора присваивания.
Теперь, когда у вас есть конструктор копирования и деструктор, вы можетеТеперь напишите оператор присваивания.Используемая здесь техника - это идиома копирования / обмена
#include <algorithm>
//...
template <typename T>
Stack<T>& Stack<T>::operator=(const Stack<T> &stack_obj)
{
if ( &stack_obj != this )
{
Stack<T> temp(stack_obj);
std::swap(top, temp.top);
std::swap(size, temp.size);
}
return *this;
}
Верьте или нет, это работает.Код, который был здесь, был перемещен в конструктор копирования, и, таким образом, оператор присваивания использует конструктор копирования.
Для краткого пояснения код создает временный объект Stack<T>
изпередано в stack_obj
(вот почему вам нужен конструктор рабочей копии).Затем все, что нужно сделать, это поменять this
членов с временными членами.Наконец, temp
умирает со старыми данными (вот почему деструктор должен работать правильно).
Обратите внимание, что вам нужно поменять местами все члены, поэтому, если вы добавите больше членов в класс Stack<T>
, вам необходимо поменять их местами в операторе присваивания.
Как только вы получитеОсновные 3 функции (копирование, назначение, уничтожение) написаны правильно, тогда и только тогда вы должны писать функции, которые возвращают Stack<T>
по значению, или писать функции, которые принимают Stack<T>
по значению.
У вас могут быть другие проблемы с operator +
, которые выходят за рамки того, что этот ответ представляет вам, но суть в том, что ваш класс требует, чтобы он имел правильную семантику копирования перед реализацией +
,