Я довольно плохо знаком с 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;
}
Как я могу изменить его так, я могу дать такой маркер?
В 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
.)
Причина, по которой вы не можете вернуть здесь NULL, заключается в том, что вы объявили свой возвращаемый тип как Attr &
. Завершающие &
делают возвращаемое значение «ссылкой», которая, по сути, является указателем на существующий объект, который не может быть нулевым. Если вы хотите иметь возможность возвращать значение null, измените Attr &
на Attr *
.
Здесь есть несколько возможных ответов. Вы хотите вернуть то, что может существовать. Вот несколько вариантов, от наименее предпочтительных до наиболее предпочтительных:
Возврат по ссылке и сигнал «невозможно найти по исключению».
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, так что в ближайшем будущем это будет «стандарт».
Если вы хотите вернуть значение NULL
, вам нужно использовать указатели вместо ссылок.
Ссылки сами по себе не могут быть NULL
.
(Примечание к будущим постерам с комментариями: да, вы можете сделать адрес ссылки NULL, если вы действительно попытаетесь это сделать).
См. В моем ответе список различий между ссылками и указателями .
Вы не можете вернуть NULL
, потому что возвращаемый тип функции - объектная ссылка
, а не указатель
.
Вы можете легко создать статический объект, который представляет возврат 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;