Почему не поймать блокировать долю в блоке 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 объявляет объект и пытается его инициировать, и способ, которым вы его инициируете, генерирует исключение, он будет пойман.