Примечание: это вторая попытка
Как исключения предназначены для использования в C ++?
; Я надеюсь, что на этот раз я очень ясно проясняю, что мой вопрос в основном о том, когда и как
поймать исключения, а не о том, когда их бросить) < /p>
< /blockquote>
Примечание: то, что я хочу знать, является то, как предполагаются исключения, которые используются в соответствии с людьми, которые пишут C ++, и, если соответствующие посторонние практические практики (в соответствии с другими практическими характеристиками. Пожалуйста, воздержитесь от всего, что может привести к тому, что этот вопрос будет закрыт как основанный на мнениях. Прочитайте файл, который не существует или без соответствующих разрешений), необходима обработка ошибок, что может быть сделано с помощью кодов возврата или исключений. (Соответствующее руководство по основной основе)
Код: Выделить всё
try
Код: Выделить всё
catch
Код: Выделить всё
catch
[*] Однако исключения должны всегда помнить, какая функция может бросить, и должным образом заботиться о безопасности исключения, чтобы написать код, которая обеспечивает базовую гарантию, сильную гарантию или гарантию «не», в зависимости от того, что имеет смысл для этой функции. /> почему я думаю, что я недостаточно знаю: < /strong> < /p>
- Несколько лет назад я пытался применить это при написании кода, который должен был прочитать файл конфигурации JSON, который выглядел в основном, как это с большим количеством полей).содержал несколько вызовов в parseconfig () , чтобы анализировать различные файлы конфигурации, я бы не знал, какой файл ошибка синтаксиса была в одном
Код: Выделить всё
{ "fields": [ { "label": "SomeField", "type": "int", "value": 5 }, { "label": "SomeOtherField", "type": "float", "value": 3.1 }, { "label": "YetAnotherField", "type": "float", "value": 8 }, ... ] } < /code> Мой код использовал Boost json, и был в основном примерно так: < /li> < /ul> void parseField(ParsedConfiguration& config, boost::json::object field) { auto const label = field.at("label"); auto const type = field.at("type"); auto const value = field.at("value"); // Do stuff } ParsedConfiguration parseConfig(char const* configFilePath) { ParsedConfiguration config; // Use fstream to read the file, and pass lines to boost::json::stream_parser boost::json::value const parsed = parseJsonFile(configFilePath); // Put fields in a list list fields; for (auto const& field : parsed.as_value().at("fields").as_array()) // May throw { fields.push_back(field.as_object()); // May throw } // Read values from the field to fill the configuration object for (auto const& field : fields) { parseField(config, field); } return config: } void foo() { try { auto const config = parseConfig("/path/to/config"); doStuff(config); } catch (std::exception const& e) { cout < /ul> < /li> Но тогда произошло то, что я запустил этот код с файлом конфигурации, в котором была синтаксическая ошибка. Было брошено исключение, было поймано исключение, и я получил сообщение об ошибке, которое было чем -то вроде: < /li> < /ul> Could not parse config: std::invalid_argument: 'value' not found < /code> И нет никакого способа узнать, какие из десятков или сотен полей не хватали записи, в контексте, кроме того, не было, что на самом низком уровне, где была обнаружена ошибка. Если foo ()
Это была глубоко неудовлетворительной и, вероятно, показывает, что я делаю что -то не так
- Я могу попытаться добавить контекст, в котором у меня есть немного, используя std :: throw_with_nested :
{
auto const label = field.at("label");
try
{
auto const type = field.at("type");
auto const value = field.at("value");
// Do stuff
}
catch (...)
{
std::throw_with_nested(std::runtime_error{std::string{"Could not parse field "} + label});
}
}
ParsedConfiguration parseConfig(char const* configFilePath)
{
try
{
.
.
.
}
catch (...)
{
std::throw_with_nested(std::runtime_error{std::string{"Could not parse config file "} + configFilePath});
}
}
< /code>
, которые могут работать для предполагаемой цели, и это также позволяет думать об исключениях как часть интерфейса функции и документировать, какие исключения могут быть выбраны при каких условиях < /li>
Это приводит к тому, что кажется множеству кода, и, кажется, противоречит целую идею. /> Это также напоминает то, что это основное руководство перечисляет в «неправильном обращении с исключением», как «классы исключения по проектированию в подсистеме по подсистеме», поэтому я не думаю, что я иду в правильном направлении здесь < /li>
< /ul>
обратно к вопросу (S) < /rest> < /p>
Неправильно? < /li>
Какова хорошая практика здесь? Являются ли исключения неправильным инструментом, чтобы сообщить, какая запись отсутствует из какого поля конфигурации? Что я должен использовать вместо этого?>
Подробнее здесь: https://stackoverflow.com/questions/796 ... ctice-here