почему блок catch не разделяет область действия блока try? - PullRequest
12 голосов
/ 29 марта 2011

Удивительно, но я не могу найти ответ на этот вопрос путем поиска в Google и поиска по 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, я полагаю?

Я понимаю, что область действия определяется блоком {}, но это кажется разумным случаем, хм, исключения.Является ли причиной того, что объекты могут быть построены не полностью, если выдается исключение?

Ответы [ 4 ]

20 голосов
/ 29 марта 2011

Имеет ли блок catch общий вид блока try?

номер

Как вы справляетесь с этим? Выдвинув std::string fname; из try, я полагаю?

Да.

Я понимаю, что область действия определяется блоком {}, но это кажется разумным случаем, хм, исключения. Является ли причиной того, что объекты могут быть построены не полностью, если выдается исключение?

Последнее, что нужно C ++, - это более сложные правила и исключения из правил. : -)

5 голосов
/ 29 марта 2011

Существует очевидная причина: вы не можете доверять состоянию объектов, которые были созданы внутри блока try.Код там был прерван из-за исключения, их конструкторы могли даже не запускаться.

3 голосов
/ 29 марта 2011

Хотя сообщение Джеймса правильно отвечает на ваши вопросы, оно не предлагает обычного обходного пути: 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";
}
0 голосов
/ 29 марта 2011

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

...