Возвратите “ПУСТОЙ” объект если результат поиска, не найденный

Я довольно плохо знаком с C++, таким образом, я склонен разрабатывать с большим количеством измов Java, в то время как я учусь. Так или иначе, в Java, если бы у меня был класс с 'поисковым' методом, который возвратил бы объект T от a Collection< T > это соответствовало определенному параметру, я возвращу тот объект и если бы объект не был найден в наборе, то я возвратился бы null. Затем в моей функции вызова я просто проверил бы if(tResult != null) { ... }

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

Это - то, на что мой код похож прямо сейчас:

class Node {
    Attr& getAttribute(const string& attribute_name) const {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return NULL; // what should this be?
    }

private:
    vector<Attr> attributes;
}

Как я могу изменить его так, я могу дать такой маркер?

91
задан Nic Hartley 3 June 2016 в 03:56
поделиться

6 ответов

В C ++ ссылки не могут быть нулевыми. Если вы хотите при желании вернуть null, если ничего не найдено, вам нужно вернуть указатель, а не ссылку:

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

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

(Кстати, меня немного беспокоит, что ваш метод const и возвращает атрибут, отличный от const . Из философских соображений я бы предложил вернуть ] const Attr * . Если вы также можете изменить этот атрибут, вы можете перегрузить его методом, отличным от const , который также возвращает атрибут, отличный от const .)

66
ответ дан 24 November 2019 в 06:49
поделиться

Причина, по которой вы не можете вернуть здесь NULL, заключается в том, что вы объявили свой возвращаемый тип как Attr & . Завершающие & делают возвращаемое значение «ссылкой», которая, по сути, является указателем на существующий объект, который не может быть нулевым. Если вы хотите иметь возможность возвращать значение null, измените Attr & на Attr * .

1
ответ дан 24 November 2019 в 06:49
поделиться

Здесь есть несколько возможных ответов. Вы хотите вернуть то, что может существовать. Вот несколько вариантов, от наименее предпочтительных до наиболее предпочтительных:

  • Возврат по ссылке и сигнал «невозможно найти по исключению».

     Attr & getAttribute (const string & attribute_name) const 
     {
     // поисковая коллекция 
     // если найдено в i 
    return attributes [i]; {{ 1}} // если не найден 
    throw no_such_attribute_error; 
    } 

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

  • Возврат по указателю

     Attr * getAttribute (const string & attribute_name) const 
     {
     // поиск по коллекции 
     // если найдено в i 
    return & attributes [i]; 
     // если не найдено 
    return nullptr; 
    } 

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

  • Используйте Boost.Optional

     boost :: optional  getAttribute (const string & attribute_name) const 
     {
     // поиск по коллекции 
     // если найдено в i 
    return attributes [i]; 
     // если не найдено 
    return boost :: optional  (); 
    } 

A boost :: optional означает, что именно здесь происходит, и имеет простые методы проверки того, был ли найден такой атрибут.


Дополнительное примечание: std :: optional недавно был включен в C ++ 17, так что в ближайшем будущем это будет «стандарт».

55
ответ дан 24 November 2019 в 06:49
поделиться

Если вы хотите вернуть значение NULL , вам нужно использовать указатели вместо ссылок.

Ссылки сами по себе не могут быть NULL .

(Примечание к будущим постерам с комментариями: да, вы можете сделать адрес ссылки NULL, если вы действительно попытаетесь это сделать).

См. В моем ответе список различий между ссылками и указателями .

3
ответ дан 24 November 2019 в 06:49
поделиться

Вы не можете вернуть NULL, потому что возвращаемый тип функции - объектная ссылка, а не указатель.

0
ответ дан 24 November 2019 в 06:49
поделиться

Вы можете легко создать статический объект, который представляет возврат NULL.

class Attr;
extern Attr AttrNull;

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
   //search collection 
   //if found at i 
        return attributes[i]; 
   //if not found 
        return AttrNull; 
} 

bool IsNull(const Attr& test) const {
    return &test == &AttrNull;
}

 private: 
   vector<Attr> attributes; 
};

И где-то в исходном файле:

static Attr AttrNull;
22
ответ дан 24 November 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: