В библиотеке у меня есть функция, которая ищет ключ в базе данных и возвращает неконстантную ссылку на объект. Я хочу обработать случай, когда ключ не найден, что обычно вызвано ошибкой при вызове функции. Эта ситуация настолько плоха, что программа не может продолжить работу, поэтому я распечатываю сообщение, чтобы помочь обнаружить ошибку, и вызываю exit(1). Проблема с оператором return, который никогда не будет выполнен в этом случае, но все равно должен быть там. Если бы это был указатель, я мог бы просто return nullptr;, но со ссылкой? Должен ли я сделать что-то вроде этого псевдокода?

 Type & get(const Key & k) {
     if (my_db.key_exists(k)) {
       return my_db.at(k);
     }
     std::cerr << k << " not found\n";
     exit(1); 
     return *(new Type(some_dummy_parameters));
 }

Это выглядит так ужасно! Может мне стоит просто избегать такой функции. Пожалуйста, дайте мне знать ваше мнение!

3
DarioP 3 Апр 2014 в 20:09
Вам не нужен оператор return, так как вы никогда не дойдете до конца функции. (Однако некоторые компиляторы могут предупредить.)
 – 
James Kanze
3 Апр 2014 в 20:41
Да, все дело было в том, чтобы избежать предупреждений компилятора ... но, поскольку количество полученных предложений, я теперь рассматриваю возможность использования исключений. Даже если они не вызывают дамп ядра, они все равно выглядят как лучший способ выйти из функции.
 – 
DarioP
3 Апр 2014 в 21:09
Я не возражаю против других комментариев по этому поводу. Я стараюсь полностью избегать exit в C++ (поскольку он не вызывает деструкторы каких-либо локальных переменных) и распространять ошибки до main, откуда я могу вернуться.
 – 
James Kanze
4 Апр 2014 в 12:11
Вероятно, вам следует использовать исключения, как указано в ответах. Однако с технической точки зрения вы можете решить проблему, изменив смысл вашего теста. Используйте !my_db.key_exists(k) в операторе if.
 – 
kec
19 Дек 2014 в 02:02

4 ответа

Лучший ответ

Эта ситуация настолько плохая, что программа не может продолжить работу, поэтому я распечатываю сообщение, чтобы помочь обнаружить ошибку, и вызываю exit (1).

Нет. Если этот код является частью библиотеки, она не должна решать, следует ли завершать приложение или нет.

Что делать, если файл открыт и его нужно закрыть, или какой-то другой ресурс нужно очистить, или если пользователь вашего класса БД хочет зарегистрировать ошибку и продолжить делать что-то еще?

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

Вы не поверите, но существовала коммерческая библиотека БД, которая делала именно то, что вы делаете (закрываете приложение). Они получили много гневных откликов от пользователей своей библиотеки о том, почему они неожиданно закрывают приложение. И вы знаете, что - ответ, данный клиентам, заключался в том, что «мы чувствовали, что ошибка была достаточно серьезной, чтобы остановить приложение, потому что наша библиотека не может продолжать работать должным образом». Это не только плохие доводы, это граничит с высокомерием, и покупатели дают им знать об этом.

9
PaulMcKenzie 23 Ноя 2018 в 11:02
Я мог бы создать исключение, но я не могу заставить пользователя поймать его. Если по какой-либо причине он этого не сделает, это станет дампом ядра. Это лучше, чем вызов exit()?
 – 
DarioP
3 Апр 2014 в 20:40
1
Если вы четко документируете, какие исключения выбрасываются из ваших функций, а пользователь отказывается читать документы и не выполняет попытку/отлов, то это их проблема, если их программа дает сбой, а не ваша.
 – 
PaulMcKenzie
3 Апр 2014 в 20:42
Мне нравится этот ответ, личный опыт и анекдоты заставляют вас больше рассуждать, чем люди, говорящие «делай то-то и то-то»!
 – 
DarioP
3 Апр 2014 в 21:22

Исключения

Это обычная ситуация во многих программах. Чтобы преодолеть это, используются исключения.

  • Для обработки непредвиденных ситуаций из кода создаются и «выбрасываются» новые исключения.
  • Затем они должны быть «пойманы» программой, вызывающей функцию.

Подробнее об исключениях можно узнать здесь.

Надеюсь это поможет.

4
Tanmay Patil 3 Апр 2014 в 20:14

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

Type & get(const Key & k) {
     if( !my_db.key_exists(k) ) {
          std::stringstream error;
          error << "key " << k << " not found";
          throw std::runtime_error(error);
     }
     return my_db.at(k);
}
3
Massa 3 Апр 2014 в 20:33

Библиотека никогда не должна выходить из приложения хозяйки.

Используйте «return null», переходите в «несогласованное состояние», при котором при каждом вызове вы возвращаете NULL.
пользователь библиотеки должен будет справиться с этим.

Или исключения ...

1
evenro 3 Апр 2014 в 20:14