2015-07-15 3 views
2

Предположим, что у нас есть класс (назовем его classs) конструктором по умолчанию, который может вызвать какое-то исключение. Мне нужно использовать объект этого класса в функции следующим образом:Исключение инициализации по умолчанию Исключение

try{ 
    classs c; 
} catch(bad_init& b){ 
    //log 
} 
//if the class initialized succesfully 
//do some with c 

Но c объявлен в блок определения области try «s и, следовательно, не видна в области видимости функции. Как я могу это сделать?

Я не хочу обертывать тело всей функции, потому что есть какой-то код, бросающий другой вид исключения.

+0

Я не думаю, что вы можете использовать ключевые слова как имена переменного/класса –

+0

@EdHeal обновленных –

+1

@ St.Antario ... объявляйте 'c' в качестве указателя перед блоком' try' и выделяйте его с помощью новой внутри 'try'. – sgarizvi

ответ

2

Вы не можете сделать это напрямую. Пока c имеет объем, код имеет право предположить, содержит ли живой объект типа classs. Если конструктор генерирует исключение, c не будет инициализирован и не может быть сохранен.

Правильный способ сделать это - обернуть весь объем c в блоке try. В конце концов, код, который использует c, не может сделать ничего значимого, если c не удалось инициализировать. Если какой-либо другой код позже в этом блоке может отбросить другие исключения, и вы не захотите их поймать, просто не разрешите им распространять стек обычно.

Если вы не можете использовать этот подход по какой-то причине, вы можете прибегнуть к чему-то вроде boost::optional и отсроченной INIT:

boost::optional<classs> c; 
try { 
    c = classs(); 
} catch (bad_init&) { 
} 

Или сделать что-то подобное вручную с std::aligned_storage, размещение new и условный вызов деструктора.

+0

Но что, если мне нужно поймать другое исключение? –

+1

@ St.Antario Просто добавьте еще одну опцию 'catch' для нее. У вас может быть столько предложений 'catch' с одним блоком' try', как вы хотите. – Angew

+0

Поймите, спасибо –

2

обходной путь заключается в использовании std::unique_ptr:

std::unique_ptr<A> a; 
try{ 
    a = std::make_unique<A>(); 
} catch(bad_init& b){ 
    //log 
} 
if (a){ 
//do 
} 
1

Я бы просто поймать исключение на уровне вызывающего абонента. Не нужно усложнять ситуацию.

void functionThatThrows() 
{ 
    classs c; 
    // do something with c 
} 

void callerThatCatches() 
{ 
    try { 
     functionThatThrows(); 
    } catch(...) { 
     // handle exception 
    } 
} 
1

Самый простой способ просто расширить блок TRY, пока вам больше не нужен ваш объект:

try{ 
    classs c; 
    //if the class initialized succesfully 
    //do some with c 
} catch(bad_init& b){ 
    //log 
} 
+1

ammm .. болтающийся указатель? –

+0

@DavidHaim: Oups :-(, спасибо, что заметили ... –

Смежные вопросы