нет оператора возврата в функции, возвращающей не void - PullRequest
0 голосов
/ 29 февраля 2012

Я новичок в кодировании, и я получаю "ошибка: нет оператора возврата в функции, возвращающей не void" для этого кода:

template <class T>
T Stack<T>::pop()
{
  `myStack.pop_front();
}
template <class T>
T Stack<T>::peek() const
{
  myStack.front();
}

Есть идеи, что я делаю неправильно?спасибо!

Ответы [ 6 ]

3 голосов
/ 29 февраля 2012

Подпись функции:

template <class T> T Stack<T>::pop()

сообщает компилятору, что ваша функция возвратит type T, однако ваша функция фактически не возвращает никакого значения, и, следовательно, компилятор дает вам предупреждение о возможной глупой ошибке с вашей стороны.

Так что вам в вашем случае нужно убедиться, что заявления,
myStack.pop_front(); & myStack.front(); фактически возвращает тип T.

Если вы используете какой-то стандартный контейнер библиотеки, pop_front(); просто удаляет первый элемент в контейнере, но ничего не возвращает.

1 голос
/ 29 февраля 2012

Вы должны добавить ключевое слово return :

template <class T>
T Stack<T>::pop()
{
  return myStack.pop_front();
}
template <class T>
T Stack<T>::peek() const
{
  return myStack.front();
}

или что-то подобное, в зависимости от того, как вы используете stack.

0 голосов
/ 20 апреля 2012

Хотя кратковременное решение - возвращать значение, лучше, если pop() имеет тип void.

template <typename T>
void Stack<T>::pop() {
    ...
}

Причина в том, что вы не можете написать исключительную pop() -функцию, которая возвращает что-то:

template <typename T>
T Stack<T>::pop() {
    T foo = stor_.top(); // May throw.
    stor_.pop(); // This line shall never throw.
    return foo;  // May throw.
}

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

Первая и третья строка могут быть сброшены, потому что данные копируются.

Теперь представьте, что

    T foo = stor_.top(); // May throw.
    stor_.pop(); // This line shall never throw.

работает безупречно: у вас есть готовое к возвращению значение, и вы успешно изменили состояние удерживающего объекта.

Но тогда

    return foo;  // May throw.

Взрыв Это исключение. Что случилось:

  • Функция не удалась, абонент не получил ничего, кроме исключения
  • Тем не менее, состояние объекта было изменено.
  • И никто больше не имеет обновленной копии утерянного объекта, которая обычно содержит важные деловые данные, которые босс позвонил несколько секунд назад, прежде чем произошел несчастный случай со смертельным исходом

Это противоречит Гарантии Авраама :

  • Гарантия отсутствия бросков: операция не вызовет исключение.

  • Сильная гарантия: что операция либо успешно завершена, либо вызвала исключение, оставляя состояние программы в точности таким, каким оно было до начала операции.

  • Основная гарантия: что инварианты компонента сохранены, а ресурсы не просочились. Часто упоминается как слабая гарантия, поскольку после исключения система остается в безопасном, но неизвестном состоянии.

И с pop(), который возвращает значение, вы не можете гарантировать, что никакая информация не будет потеряна.

См. Также ПОЛУЧИЛ # 8 и ПОЛУЧИЛИ # 82

0 голосов
/ 29 февраля 2012

Это будет работать:

 template <class T>
    void Stack<T>::pop()
    {
      `myStack.pop_front();
    }
    template <class T>
    void Stack<T>::peek() const
    {
      myStack.front();
    }

Или:

template <class T>
T Stack<T>::pop()
{
  `myStack.pop_front();
  // return something of type T
}
template <class T>
T Stack<T>::peek() const
{
  myStack.front();
  //return something of type T
}
0 голосов
/ 29 февраля 2012

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

template <class T>
T Stack<T>::peek()
{
  return myStack.front();
}
0 голосов
/ 29 февраля 2012

Ваша подпись просит вас вернуть объект типа T.

template <class T> T Stack<T>::pop()

Если разбить это немного, template <class T> означает, что для каждого класса, который вы вставите для T, будет сгенерирована другая копия кода. Например, если вы сделали

Stack intStack; Стек двойной стек;

Компилятор сгенерирует две копии вашего класса Stack: одну специализированную для int, а другую для double.

Итак, когда вы пишете

template <class T>
T Stack<T>::pop()
{
  myStack.pop_front();
}

вам нужно вернуть объект специализированного типа. pop_front () удаляет только первый элемент. Вам нужно получить к нему доступ, удалить первый элемент и вернуть его.

Возможно, это не лучший способ сделать это, но чтобы проиллюстрировать мою точку зрения

template <class T>
T Stack<T>::pop()
{
  T tmp = myStack.front();
  myStack.pop_front();
  return tmp;
}
...