Почему не поймать блокировать долю в блоке try?
Удивительно, но я не могу найти ответ на этот вопрос по поиску и поиску SO (на SO есть много похожих вопросов, но связанных с другими языками).
Я подозреваю, что ответ no
. Если это так, возникает очевидное неудобство, например
try
{
std::string fname = constructFileName(); // can throw MyException
ofstream f;
f.exceptions(ofstream::failbit | ofstream::badbit);
f.open(fname.c_str());
// ...
}
catch (ofstream::failure &e)
{
cout << "opening file " << fname << " failed\n"; // fname is not in the scope
}
catch (MyException &e)
{
cout << "constructing file name failed\n";
}
Если мое предположение верно, как вы справляетесь с этим? Перемещая std::string fname;
из try
, я предполагаю?
Я понимаю, что область видимости определяется блоком {}
, но это кажется разумным случаем для исключения hmm. Является ли причина того, что объекты могут быть не полностью построены, если выбрано исключение?
Ответы
Ответ 1
Блокирует ли блок catch
область действия блока try
?
Нет.
Как вы справляетесь с этим? Перемещая std::string fname;
из try
, я предполагаю?
Да.
Я понимаю, что область видимости определяется блоком {}
, но это кажется разумным случаем для исключения hmm. Является ли причина того, что объекты могут быть не полностью построены, если выбрано исключение?
Последнее, что требуется С++, - это более сложные правила и исключения из правил.: -)
Ответ 2
Есть очевидная причина: вы не можете доверять состоянию объектов, которые были созданы внутри блока try. Код там был прерван исключением, их конструкторы, возможно, еще не запущены.
Ответ 3
В то время как сообщение Джеймса правильно отвечает на ваши вопросы, оно не обеспечивает обычное обходное решение: swap
. Предполагая, что constructFileName()
возвращает std::string
, а не char const*
, следующее идиоматично:
std::string fname;
try
{
constructFileName().swap(fname); // can throw MyException
std::ofstream f;
f.exceptions(std::ios_base::failbit | std::ios_base::badbit);
f.open(fname.c_str());
// ...
}
catch (std::ios_base::failure &e)
{
std::cout << "opening file " << fname << " failed\n";
}
catch (MyException &e)
{
std::cout << "constructing file name failed\n";
}
Ответ 4
Они находятся за пределами области действия. Это потому, что если u объявляет объект и пытается его инициировать, и способ, которым вы его инициируете, генерирует исключение, он будет пойман.