Существенной частью любой программы является обработка
Первый вид
Теоретически возможно написать программу без таких
Перечислим некоторые средства языка, которые помогут избежать
Самым важным средством уменьшения вероятности
Несмотря на все эти положительные качества языка, остается "простор"
для написания
Лучше исходить из того, что идеальных программ не существует, это
помогает разрабатывать более надежные программы. Самое главное –
обеспечить контроль данных, а для этого необходимо проверять в программе
все, что может содержать
Ну и решающими качествами, позволяющими уменьшить количество
Второй вид
Именно обработка двух последних видов
Простейший способ сообщения об true в
случае успешного сохранения, false – в случае
class Database
{
public:
bool SaveObject(const Object obj);
};
Соответственно, вызов метода должен выглядеть так:
if (database.SaveObject(my_obj) == false ){
//обработка ошибки
}
Обработка
int main()
{
if (fun1()==false ) //обработка ошибки
return 1;
}
bool
fun1()
{
if (fun2()==false )
return false ;
return true ;
}
bool
fun2()
{
if (database.SaveObject(obj)==false )
return false ;
return true ;
}
Если функция или метод должны возвращать какую-то величину в качестве
результата, то особое, недопустимое, значение этой величины используется в
качестве признака
Иногда невозможно вернуть признак
Распространенным решением является дополнительный атрибут
объекта – флаг, отражающий состояние объекта. Предположим, конструктор
класса Database должен соединиться с сервером базы данных.
class Database
{
public :
Database(const char *serverName);
...
bool Ok(void) const {return okFlag;};
private :
bool okFlag;
};
Database::Database(const char*serverName)
{
if (connect(serverName)==true )
okFlag =true ;
else
okFlag =false ;
}
int main()
{
Database database("db-server");
if (!database.Ok()){
cerr <<"Ошибка соединения с базой данных"<<endl;
return 0;
}
return 1;
}
Лучше вместо метода Ok, okFlag,
переопределить операцию ! (отрицание).
class Database
{
public :
bool operator !()const {return !okFlag;};
};
Тогда проверка успешности соединения с базой данных будет выглядеть так:
if (!database){
cerr <<"Ошибка соединения с базой
данных"<<endl;
}
Следует отметить, что лучше избегать такого построения классов,
при котором возможны Open:
class Database
{
public :
Database();
bool Open(const char*serverName);
}
и тогда отпадает необходимость в операции ! или методе Ok().
Использование if с проверкой на
В языке Си++ реализован специальный механизм для сообщения
об
throw. В качестве аргумента throw задается любое значение. Это может
быть значение одного из встроенных типов (число, строка символов и
т.п.) или объект любого определенного в программе класса.
При возникновении main и, соответственно, вся программа.
Предположим, из main была вызвана функция foo, которая вызвала
метод Open, а он в свою очередь возбудил
class Database
{
public :
void Open(const char*serverName);
};
void
Database::Open(const char*serverName)
{
if (connect(serverName)==false )
throw 2;
}
foo()
{
Database database;
database.Open("db-server");
String y;
...
}
int main()
{
String x;
foo();
return 1;
}
В этом случае управление вернется в функцию foo, будет вызван деструктор
объекта database, управление вернется в main, где будет вызван
деструктор объекта x, и выполнение программы завершится. Таким образом,
В таком виде оператор throw используется для действительно
В программе можно объявить блок, в котором мы будем отслеживать try и catch:
try {
...
}catch (тип_исключительной_операции){
...
}
Если внутри блока try возникла catch. Тип throw. Если тип catch, выполняется блок catch. Тип аргумента catch совместим, если он либо совпадает с типом ситуации, либо
является одним из ее базовых типов. Если тип несовместим, то происходит
описанный выше catch с подходящим типом аргумента.
В блоке catch происходит обработка
foo()
{
Database database;
int attempCount =0;
again:
try {
database.Open("dbserver");
} catch (int x){
cerr <<"Ошибка соединения номер "
<<x <<endl;
if (++attemptCount <5)
goto again;
throw ;
}
String y;
...
}
Ссылка на аргумент throw передается в блок catch.
Этот блок гасит catch можно создать
либо ту же самую throw без аргументов, либо другую, или же не создавать никакой. В последнем
случае catch.
С одним блоком try может быть связано несколько блоков catch с
разными аргументами. В этом случае catch до тех пор, пока аргумент не
окажется совместимым. Этот блок и выполняется. Специальный вид catch
catch (...)
совместим с любым типом
Механизм
Прежде всего, имеет смысл определить для них специальный класс.
Простейшим вариантом является класс, который может хранить код
class Exception
{
public :
enum ErrorCode {
NO_MEMORY,
DATABASE_ERROR,
INTERNAL_ERROR,
ILLEGAL_VALUE
};
Exception(ErrorCode errorKind,
const String errMessage);
ErrorCode GetErrorKind(void )const
{return kind;};
const String GetErrorMessage(void )const
{return msg;};
private :
ErrorCode kind;
String msg;
};
Создание
if (connect(serverName)==false )
throw Exception(Exception::DATABASE_ERROR,
serverName);
А проверка на
try {
...
}catch (Exception e){
cerr <<"Произошла ошибка "<<e.GetErrorKind()
<<"Дополнительная информация:"
<<e.GetErrorMessage();
}
Преимущества класса перед просто целым числом состоят, во-первых,
в том, что передается дополнительная информация и, во-вторых, в операторах catch можно реагировать только на
throw AnotherException;
то блок catch будет пропущен: он ожидает только Exception. Это особенно существенно при сопряжении нескольких
различных программ и библиотек – каждый набор классов отвечает только за собственные
В данном случае код Exception.
Если в одном блоке catch ожидается несколько разных if или switch.
try {
...
}catch (Exceptione){
cerr <<"Произошла ошибка "<<e.GetErrorKind()
<<"Дополнительная информация:"
<<e.GetErrorMessage();
if (e.GetErrorKind()==Exception::NO_MEMORY ||
e.GetErrorKind()==
Exception::INTERNAL_ERROR)
throw ;
else if (e.GetErrorKind()==
Exception::DATABASE_ERROR)
return TRY_AGAIN;
else if (e.GetErrorKind()==
Exception::ILLEGAL_VALUE)
return NEXT_VALUE;
}
Другим методом разделения различных
(рис 16.1) Пример иерархии классов для представления исключительных ситуаций.
В приведенной на рисунке 16.1 структуре классов все DatabaseException ), и внутренние InternalException). В свою очередь, ConnectDbException)
и ReadDbException). Внутренние NoMemoryException) и недопустимые значения
(IllegalValException).
Теперь блок catch может быть записан в следующем виде:
try {
}catch (ConnectDbExceptione ){
//обработка ошибки соединения с базой данных
}catch (ReadDbExceptione){
//обработка ошибок чтения из базы данных
}catch (DatabaseExceptione){
//обработка других ошибок базы данных
}catch (NoMemoryExceptione){
//обработка нехватки памяти
}catch (…){
//обработка всех остальных исключительных
//ситуаций
}
Напомним, что когда при проверке catch проверка идет последовательно до тех
пор, пока не найдется подходящий тип. Поэтому, например, нельзя ставить catch для класса DatabaseException впереди catch для класса ConnectDbException – ConnectDbException
совместима с классом DatabaseException (это ее базовый класс), и она будет
обработана в catch для DatabaseException и не дойдет до блока с ConnectDbException.
Построение системы классов для разных
Чтобы облегчить обработку
class Database
{
public :
Open(const char*serverName)
throw ConnectDbException;
};
Такое описание говорит о том, что метод Open класса Database
может создать ConnectDbException. Соответственно,
при использовании этого метода желательно предусмотреть
обработку возможной
В заключение приведем несколько рекомендаций по использованию
throw, освободите ресурсы, зарезервированные
в текущей функции. Например, если какой-либо объект был создан с помощью new, необходимо явно вызвать для него delete.Если
Существенной частью любой программы является обработка
Первый вид
Теоретически возможно написать программу без таких
Перечислим некоторые средства языка, которые помогут избежать
Самым важным средством уменьшения вероятности
Несмотря на все эти положительные качества языка, остается "простор"
для написания
Лучше исходить из того, что идеальных программ не существует, это
помогает разрабатывать более надежные программы. Самое главное –
обеспечить контроль данных, а для этого необходимо проверять в программе
все, что может содержать
Ну и решающими качествами, позволяющими уменьшить количество
Второй вид
Именно обработка двух последних видов
Простейший способ сообщения об true в
случае успешного сохранения, false – в случае
class Database
{
public:
bool SaveObject(const Object obj);
};
Соответственно, вызов метода должен выглядеть так:
if (database.SaveObject(my_obj) == false ){
//обработка ошибки
}
Обработка
int main()
{
if (fun1()==false ) //обработка ошибки
return 1;
}
bool
fun1()
{
if (fun2()==false )
return false ;
return true ;
}
bool
fun2()
{
if (database.SaveObject(obj)==false )
return false ;
return true ;
}
Если функция или метод должны возвращать какую-то величину в качестве
результата, то особое, недопустимое, значение этой величины используется в
качестве признака
Иногда невозможно вернуть признак
Распространенным решением является дополнительный атрибут
объекта – флаг, отражающий состояние объекта. Предположим, конструктор
класса Database должен соединиться с сервером базы данных.
class Database
{
public :
Database(const char *serverName);
...
bool Ok(void) const {return okFlag;};
private :
bool okFlag;
};
Database::Database(const char*serverName)
{
if (connect(serverName)==true )
okFlag =true ;
else
okFlag =false ;
}
int main()
{
Database database("db-server");
if (!database.Ok()){
cerr <<"Ошибка соединения с базой данных"<<endl;
return 0;
}
return 1;
}
Лучше вместо метода Ok, okFlag,
переопределить операцию ! (отрицание).
class Database
{
public :
bool operator !()const {return !okFlag;};
};
Тогда проверка успешности соединения с базой данных будет выглядеть так:
if (!database){
cerr <<"Ошибка соединения с базой
данных"<<endl;
}
Следует отметить, что лучше избегать такого построения классов,
при котором возможны Open:
class Database
{
public :
Database();
bool Open(const char*serverName);
}
и тогда отпадает необходимость в операции ! или методе Ok().
Использование if с проверкой на
В языке Си++ реализован специальный механизм для сообщения
об
throw. В качестве аргумента throw задается любое значение. Это может
быть значение одного из встроенных типов (число, строка символов и
т.п.) или объект любого определенного в программе класса.
При возникновении main и, соответственно, вся программа.
Предположим, из main была вызвана функция foo, которая вызвала
метод Open, а он в свою очередь возбудил
class Database
{
public :
void Open(const char*serverName);
};
void
Database::Open(const char*serverName)
{
if (connect(serverName)==false )
throw 2;
}
foo()
{
Database database;
database.Open("db-server");
String y;
...
}
int main()
{
String x;
foo();
return 1;
}
В этом случае управление вернется в функцию foo, будет вызван деструктор
объекта database, управление вернется в main, где будет вызван
деструктор объекта x, и выполнение программы завершится. Таким образом,
В таком виде оператор throw используется для действительно
В программе можно объявить блок, в котором мы будем отслеживать try и catch:
try {
...
}catch (тип_исключительной_операции){
...
}
Если внутри блока try возникла catch. Тип throw. Если тип catch, выполняется блок catch. Тип аргумента catch совместим, если он либо совпадает с типом ситуации, либо
является одним из ее базовых типов. Если тип несовместим, то происходит
описанный выше catch с подходящим типом аргумента.
В блоке catch происходит обработка
foo()
{
Database database;
int attempCount =0;
again:
try {
database.Open("dbserver");
} catch (int x){
cerr <<"Ошибка соединения номер "
<<x <<endl;
if (++attemptCount <5)
goto again;
throw ;
}
String y;
...
}
Ссылка на аргумент throw передается в блок catch.
Этот блок гасит catch можно создать
либо ту же самую throw без аргументов, либо другую, или же не создавать никакой. В последнем
случае catch.
С одним блоком try может быть связано несколько блоков catch с
разными аргументами. В этом случае catch до тех пор, пока аргумент не
окажется совместимым. Этот блок и выполняется. Специальный вид catch
catch (...)
совместим с любым типом
Механизм
Прежде всего, имеет смысл определить для них специальный класс.
Простейшим вариантом является класс, который может хранить код
class Exception
{
public :
enum ErrorCode {
NO_MEMORY,
DATABASE_ERROR,
INTERNAL_ERROR,
ILLEGAL_VALUE
};
Exception(ErrorCode errorKind,
const String errMessage);
ErrorCode GetErrorKind(void )const
{return kind;};
const String GetErrorMessage(void )const
{return msg;};
private :
ErrorCode kind;
String msg;
};
Создание
if (connect(serverName)==false )
throw Exception(Exception::DATABASE_ERROR,
serverName);
А проверка на
try {
...
}catch (Exception e){
cerr <<"Произошла ошибка "<<e.GetErrorKind()
<<"Дополнительная информация:"
<<e.GetErrorMessage();
}
Преимущества класса перед просто целым числом состоят, во-первых,
в том, что передается дополнительная информация и, во-вторых, в операторах catch можно реагировать только на
throw AnotherException;
то блок catch будет пропущен: он ожидает только Exception. Это особенно существенно при сопряжении нескольких
различных программ и библиотек – каждый набор классов отвечает только за собственные
В данном случае код Exception.
Если в одном блоке catch ожидается несколько разных if или switch.
try {
...
}catch (Exceptione){
cerr <<"Произошла ошибка "<<e.GetErrorKind()
<<"Дополнительная информация:"
<<e.GetErrorMessage();
if (e.GetErrorKind()==Exception::NO_MEMORY ||
e.GetErrorKind()==
Exception::INTERNAL_ERROR)
throw ;
else if (e.GetErrorKind()==
Exception::DATABASE_ERROR)
return TRY_AGAIN;
else if (e.GetErrorKind()==
Exception::ILLEGAL_VALUE)
return NEXT_VALUE;
}
Другим методом разделения различных
(рис 16.1) Пример иерархии классов для представления исключительных ситуаций.
В приведенной на рисунке 16.1 структуре классов все DatabaseException ), и внутренние InternalException). В свою очередь, ConnectDbException)
и ReadDbException). Внутренние NoMemoryException) и недопустимые значения
(IllegalValException).
Теперь блок catch может быть записан в следующем виде:
try {
}catch (ConnectDbExceptione ){
//обработка ошибки соединения с базой данных
}catch (ReadDbExceptione){
//обработка ошибок чтения из базы данных
}catch (DatabaseExceptione){
//обработка других ошибок базы данных
}catch (NoMemoryExceptione){
//обработка нехватки памяти
}catch (…){
//обработка всех остальных исключительных
//ситуаций
}
Напомним, что когда при проверке catch проверка идет последовательно до тех
пор, пока не найдется подходящий тип. Поэтому, например, нельзя ставить catch для класса DatabaseException впереди catch для класса ConnectDbException – ConnectDbException
совместима с классом DatabaseException (это ее базовый класс), и она будет
обработана в catch для DatabaseException и не дойдет до блока с ConnectDbException.
Построение системы классов для разных
Чтобы облегчить обработку
class Database
{
public :
Open(const char*serverName)
throw ConnectDbException;
};
Такое описание говорит о том, что метод Open класса Database
может создать ConnectDbException. Соответственно,
при использовании этого метода желательно предусмотреть
обработку возможной
В заключение приведем несколько рекомендаций по использованию
throw, освободите ресурсы, зарезервированные
в текущей функции. Например, если какой-либо объект был создан с помощью new, необходимо явно вызвать для него delete.Если
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.