2016-11-22 4 views
1

Рассмотрит следующий класс:C++: Попробуйте поймать на строительстве класса с константным членом

class MyClass 
{ 
private: 
    const unsigned int num;//num identifies the object. needs to be const 
    unsigned int checkNum(unsigned int);// verifies that num has a valid value 

public: 
    MyClass(unsigned int n): num(checkNum(n)) {} 
}; 

unsigned int MyClass:checkNum(unsigned int n) 
{ 
    if (some_condition) 
     throw std::invalid_argument("Invalid number"); 
    return n; 
} 

Трудность состоит в том, что объект должен быть построен внутри try блока из-за проверки диапазона:

int main() 
{ 
    try { 
     MyClass mc(1000); 
    } 
    catch (std::invalid_argument &ia) 
    { 
     std::cout << ia.what(); 
    } 
    return 0; 
} 

Проблема в том, что mc не доступен за пределами блока try.

Возможные решения:

  1. Расширение try блока по всей сферы, где mc используется. Во многих случаях это не практично.

  2. Не бросайте исключение в конструктор, но потом его бросить будет слишком поздно.

Единственное приемлемое решение, которое я могу думать о том, чтобы использовать смарт-указатели, чтобы принести декларацию за пределами try блока:

int main() 
{ 
    std::unique_ptr<MyClass> my_class_ptr; 
    try { 
     my_class_ptr = std::make_unique<MyClass>(1000); 
    } 
    catch (std::invalid_argument &ia) 
    { 
     std::cout << ia.what(); 
    } 
    return 0; 
} 

Есть ли другие/более эффективные решения?

+1

Я уверен, что вы имели в виду для 'checkNum' и' checkPin' одноименное имя. Пожалуйста, напишите ** реальный код ** в вопросах SO. По крайней мере, один ответ, похоже, был введен в заблуждение. –

ответ

2

В вашей точке 1 «практически не практично во многих случаях» просто неверно.

A try блок - это решение, в котором вы хотите справиться с отказом.

Альтернативой является то, что он не обрабатывается.


В других новостях, в вашем пункте 2, «Не делайте MyClass :: Num Уст. Не хорошо, это должно быть не изменяемые в течение всего срока объекта.» очень сомнительно. Это в какой-то мере зависит от личного мнения, но технически нет проблем. Кроме того, нет связи между const и проверкой диапазона: это гипотетическое соединение просто не существует.

8

Что вы намерены делать с mc, когда его строительство было признано недействительным и «отменено» через исключение?

Наличие try распространяется на весь объем объекта, имеет смысл.

mcне должен быть доступен за пределами try блока.

0

Вы должны подтвердить идентификационный номер до, связав с ним объект mc. Не делать проверку внутри самого конструктора:

class MyClass 
{ 
private: 
    const unsigned int num; 

public: 
    MyClass(unsigned int n): num(n) {} 
}; 

unsigned int checkNum(unsigned int n) 
{ 
    if (some_condition) 
     throw std::invalid_argument("Invalid number"); 
    return n; 
} 

int main() 
{ 
    unsigned int num; 
    try { 
     num = checkNum(some_input); 
    } 
    catch (std::invalid_argument &ia) 
    { 
     std::cout << ia.what(); 
     return -1; 
    } 
    MyClass mc(num); 
    return 0; 
} 
0

Вы можете использовать функцию-Try-блок, чтобы предотвратить любой хотел использовать тс вне блока Try.:>

int main() try{ 

    return 0; 
} catch(...) { 

}