Я пытаюсь сделать мой код C ++ безопасным от исключений, и у меня возникла проблема, которая не поможет ни опросу друзей, ни поиску в Интернете.
Насколько я понимаю, когда создание объекта с помощью конструктора потенциально может вызвать исключение, код для создания должен быть заключен в try
обработка блоков и исключений выполняется в catch(){}
,
Если создание основано на куче (например, new
Редактор с распределителем по умолчанию), я могу разместить код обработки исключений рядом с созданием:
void f() {
// work unrelated to Hoge object here
try {
Hoge *pHoge = new Hoge(); // could throw an exception
} catch(HogeException& ex) {
// handle exception
}
// rest of work here
}
Однако, если создание основано на стеке, я не могу найти способы сделать это и прибегнуть к коду, как показано ниже, из-за объема try
блок:
void g() {
// work unrelated to Hoge object here
try {
Hoge hoge; // could throw an exception
// rest of work here
} catch(HogeException& ex) {
// handle exception
}
}
Если // rest of work
приведенный выше код является большим, расстояние между созданием объекта и обработкой исключений может быть большим, что снижает читабельность кода …
Я предпочитаю, чтобы код обработки исключений был близок к созданию объекта (и, возможно, это одна из концепций try
—catch
состав). Есть ли какие-то решения?
Делегировать // rest of work
к вспомогательной функции и передать Hoge&
к этой функции:
void RestOfWork(Hoge& hoge)
{
// rest of work here
}
void g() {
// work unrelated to Hoge object here
try {
Hoge hoge;
RestOfWork(hoge);
// rest of work here
} catch(HogeException& ex) {
// handle exception
}
}
Между прочим, Hoge hoge();
не делает то, что вы думаете, что делает. Вы, вероятно, думаете, что объявляете объект с именем hoge
типа Hoge
и инициализировать его, вызывая конструктор по умолчанию. Что вы на самом деле делаете, это объявляете функцию с именем hoge
который не принимает параметров и возвращает Hoge
по значению. Я исправил это в моем коде выше.
редактировать Действительно, как подсказывает @LightnessRacesInOrbit, конструкция Hoge
Объект также может иметь место в функции отсрочки, например:
void RestOfWork()
{
Hoge hoge;
// rest of work here
}
void g() {
// work unrelated to Hoge object here
try {
RestOfWork();
} catch(HogeException& ex) {
// handle exception
}
}
Разумный способ сделать это — использовать обнуляемый контейнер из одного элемента, например, boost::optional
:
void g() {
// work unrelated to Hoge object here
boost::optional<Hoge> opt_hoge;
try {
opt_hoge = boost::in_place<Hoge>();
} catch(HogeException& ex) {
// handle exception
}
Hoge &hoge = *opt_hoge;
// rest of work here
}
Если вы не можете использовать Boost, std::unique_ptr
будет работать за счет кучи распределения:
void g() {
// work unrelated to Hoge object here
std::unique_ptr<Hoge> opt_hoge;
try {
opt_hoge = std::unique_ptr<Hoge>(new Hoge);
} catch(HogeException& ex) {
// handle exception
}
Hoge &hoge = *opt_hoge;
// rest of work here
}