Верните объект «нулевой», если результат поиска не найден

StackOverflow https://stackoverflow.com/questions/2639255

  •  26-09-2019
  •  | 
  •  

Вопрос

Я довольно новичок в C ++, поэтому я склонен к дизайну с множеством Java-Isms, пока я учусь. Во всяком случае, в Java, если у меня был класс с методом «поиска», который вернет объект T из Collection< T > которые соответствовали определенному параметру, я бы вернул этот объект, и если объект не найден в коллекции, я бы вернул null. Отказ Тогда в моей функции звонков я бы просто проверил if(tResult != null) { ... }

В C ++, я узнаю, что не могу вернуть 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 ++ ссылки не могут быть нулевыми. Если вы хотите необязательно вернуть нулю, если ничего не найдено, вам нужно вернуть указатель, а не ссылку:

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 атрибут тоже.)

Другие советы

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

  • Обратитесь по ссылке, а сигнал может не найти исключением.

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

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

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

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

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

  • Использовать Boost.optional

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

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


Боковая заметка: STD :: Недавно было проголосовано в C ++ 17, поэтому это будет «стандартная» вещь в ближайшем будущем.

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

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;

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

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

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

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

Как вы решили, что вы не можете сделать это так, как вы сделали в Java (или C #). Вот еще одно предложение, вы можете пропустить ссылку на объект как аргумент и возврат стоимости BOOL. Если результат найден в вашей коллекции, вы можете назначить его ссылочной передаче и возврата «True», в противном случае верните «ложь». Пожалуйста, рассмотрите этот код.

typedef std::map<string, Operator> OPERATORS_MAP;

bool OperatorList::tryGetOperator(string token, Operator& op)
{
    bool val = false;

    OPERATORS_MAP::iterator it = m_operators.find(token);
    if (it != m_operators.end())
    {
        op = it->second;
        val = true;
    }
    return val;
}

Вышеуказанная функция должна найти оператора против ключа «токен», если он найдет тот, который он возвращает True и назначить значение оператору параметров и OP.

Код звонящего для этой процедуры выглядит так

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
    //Do something here if true is returned.
}

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

Вы не можете вернуться NULL потому что тип возврата функции является объектом reference И не а pointer.

Вы можете попробовать это:

return &Type();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top