Проблема шаблонов C ++: преобразовать в ноль - PullRequest
2 голосов
/ 25 января 2011

У меня есть класс контейнера Stack, и я хочу создавать экземпляры различных типов стеков.поэтому я делаю это:

template <typename T>
class MyStack
{
.
.
   T Pop()
   {
      if(!IsEmpty())
      {
         return data[top--];
      }
      else
      {
         return NULL; // I got error here
      }
 .
 .
}

Когда я пытаюсь использовать стек следующим образом:

MyStack<GraphNode> blacks;
GraphNode t = blacks.Pop();

Я получаю эту ошибку:

conversion from ‘int’ to non-scalar type ‘GraphNode’ requested

Но когда я используютип указателя типа Stack<GraphNode*> проблем нет.Я знаю, что NULL - это 0, и я понимаю, почему возникает ошибка ... Каков элегантный способ сообщить программе, что нет данных для возврата без изменения кода?я должен добавить что-то вроде неявного оператора преобразования типов в класс?как?

ПРИМЕЧАНИЕ: Я не использую STL

Ответы [ 4 ]

6 голосов
/ 25 января 2011

Возвращая T по значению, контракт вашей функции заключается в том, что вы вернете значение. Две альтернативы - изменить контракт вашей функции (например, вместо этого вернуть T*) или не вернуться, выдав исключение.

Лично я думаю, что в данном случае допустимо и целесообразно бросить исключение. Возврат указателя или передача ссылки на перезапись и возвращение логического значения успеха являются менее чистыми решениями.

Особенно, если вы предоставляете публичный метод IsEmpty(), нет причин выбирать менее чистое решение. Клиенты, которые не хотят обрабатывать исключения, могут использовать IsEmpty, чтобы избежать получения исключения, которое становится эквивалентом утверждения.

5 голосов
/ 25 января 2011

STL std::stack разбивает эту функцию на top(), которая возвращает ссылку на последний элемент, и pop().Поведение просто не определено, если вы используете любой из них, и стек уже пуст (т.е. если empty() == true).Это не похоже на плохой подход.

3 голосов
/ 26 января 2011

Если вы еще не прочитали GoTW # 8 , вам следует сделать это сейчас.Он полностью посвящен рассматриваемому вопросу - как проектировать стек.Одним из самых основных моментов является то, что дизайн, который вы сейчас используете для pop , не может быть безопасным для исключений.

Ответ, который он дает на данный вопрос (необязательно хороший ...) должен возвращать созданный по умолчанию T, если стек пуст:

T Pop()
{
  if(!IsEmpty())
  {
     return data[top--];
  }
  else
  {
     return T(); // No more error
  }
}

Проблема с этим заключается в том, что в большинстве случаев при попытке выскочитьпустой стек указывает на логическую ошибку, и его вообще нельзя допускать.Вы можете бесконечно спорить между использованием assert или генерацией исключения, но редко можно вернуть значение, которое действительно полезно (возможное исключение - возвращение NaN, если вы имеете дело с числами FP).

3 голосов
/ 25 января 2011

По этой причине каноническая функция pop возвращает void. Кроме того, вы не вызвали деструктор данных [top], который является Bad ™.

Если сомневаетесь, проверьте STL .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...