C ++: вернуть NULL вместо структуры - PullRequest
9 голосов
/ 16 июня 2010

У меня есть структура Foo.В псевдокоде:

def FindFoo:
   foo = results of search
   foundFoo = true if a valid foo has been found  

   return foo if foundFoo else someErrorCode

Как я могу сделать это в C ++?

Отредактировано для устранения многочисленных неточностей.

Ответы [ 8 ]

13 голосов
/ 16 июня 2010

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

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

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

4 голосов
/ 16 июня 2010

Брось исключение. Вот для чего они.

3 голосов
/ 16 июня 2010

Вы можете посмотреть на boost::optional и посмотреть, соответствует ли он вашим потребностям. Однако:

вернуть foo, если foundFoo иначе someErrorCode

Это заставляет меня думать, что вам может быть лучше, если вы сгенерируете исключение, если не найдете foo.

1 голос
/ 16 июня 2010

Не является ли поиск foo действительно исключительной ситуацией?Тогда брось исключение.Ожидаете не найти Foo?пусть функция вернет код ошибки и передаст foo через опорный параметр, где foo допустима, только если функция не возвращает ошибку.

1 голос
/ 16 июня 2010

Это невозможно в C ++ без использования указателей или решения библиотеки вне стандартной библиотеки.(Boost не является частью стандартной библиотеки, это стороннее решение.)

В C # вы можете использовать Nullable<Foo>.

В отличие от комментария Билли, структуры являются типами значений, не ссылочные типы, и Nullable может применяться к любому типу значения, а не только к встроенным.Следующие компиляции просто отлично:

struct Test {
    int Blah;
}
void Main() {
    System.Nullable<Test> proof;
}
1 голос
/ 16 июня 2010

Один из способов сделать это - вернуть указатель на foo:

public Foo* findFoo()
{
    return fooFound ? new fooResult() : NULL;
}

Другая возможность определить NullFoo некоторого вида, возможно, как struct, расширяющий Foo с пустой реализацией. Для получения дополнительной информации о последней идее вы можете прочитать о шаблоне пустых объектов .

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

1 голос
/ 16 июня 2010

Это также не работает в C #.Вы должны вернуть указатель на Foo.

0 голосов
/ 16 июня 2010

Вы также не можете сделать это в C # - вам нужно вернуть new Foo(), а не null, чтобы компилятор был доволен.

То же самое в случае C ++ - вам нужно создать экземпляр структуры, если вы собираетесь возвращать по значению. Если нет, вы хотите вернуться по указателю (в этом случае вы будете new вводить или возвращать указатель на указатель, выделенный другим способом, что вносит грязную семантику передачи владения в уравнение).

РЕДАКТИРОВАТЬ: на основе вашего обновления. Похоже, вы хотите вернуть либо значение, либо мета-значение «null», которое указывает «not found». Вы можете сделать это несколькими способами:

  1. throw в случае неудачи, в противном случае безоговорочно вернуть значение
  2. возвращает указатель - но это оставляет ответственность за delet поднятие его в воздух, если оно не останется в памяти надолго
  3. оберните его в [шаблонный] объект-обертку, который обрабатывает условия так же, как это сделал бы .NET Nullable<T> (я позволю кому-то присоединиться к правильному UPDATE: @Mike Seymour говорит, что это boost::optional<foo>)
  4. использовать шаблон Null Object для возврата подходящего значения, которое правильно работает, когда рассматривается как действительный результат на стороне клиента
...