►Так что же мы будем бросать?...295
За ключевым словом throw следует выражение, которое создаёт объект некоторого типа. В приведённых здесь примерах мы генерировали переменные типа int, но на самом деле ключевое слово throw работает с любым типом объекта. Это значит, что вы можете "бросать" любое количество информации. Рассмотрим приведённое ниже определение класса.
//
/* CustomExceptionClass — демонстрация исключений */
/* при использовании факториала */
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
using namespace std ;
/* Exception — обобщённый класс исключения */
class Exception
{
public :
Exception( char* pMsg , int n , char* pFile , int nLine )
: msg( pMsg ) , errorValue( n ) , file( pFile ) , lineNum( nLine )
{ }
virtual string display( )
{
ostringstream out ;
out << "Ошибка <" << msg
<< " - значение равно " << errorValue
<< "> " ;
out << "@" << file << "-" << lineNum << endl ;
return out.str( ) ;
}
protected :
/* Сообщение об ошибке */
string msg ;
int errorValue ;
/* Имя файла и номер строки, где произошла ошибка */
string file ;
_________________
295 стр. Глава 25. Обработка ошибок и исключения
int lineNum ;
} ;
/* factorial — вычисление факториала */
int factorial( int n )
{
/* Функция не обрабатывает отрицательные значения аргумента */
if ( n < 0 )
{
throw Exception( "Аргумент факториала отрицателен" ,
n , __FILE__ , __LINE__ ) ;
}
/* Вычисляем факториал */
int accum = 1 ;
while ( n > 0 )
{
accum *= n ;
n-- ;
}
return accum ;
}
int main( int nNumberofArgs , char* pszArgs[ ] )
{
/* печать кириллицы, если Вы не установите программки gccrus.exe и g++rus.exe */
setlocale ( LC_ALL , ".1251" ) ;
try
{
/* Этот код работает корректно */
cout << "3! = " << factorial( 3 ) << endl ;
/* Здесь генерируется исключение */
cout << "Factorial of -1 is " << factorial( -1 ) << endl ;
/* Этот код остаётся невыполненным */
cout << "Factorial of 5 is " << factorial( 5 ) << endl ;
}
/* Перехват исключения */
catch( Exception e )
{
cout << "Ошибка: " << e.display( ) << endl ;
}
catch ( ... )
{
cout << "Неизвестное исключение" << endl ;
}
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
Программа выглядит практически идентичной программе вычисления факториала, приведённой в начале главы. Отличие заключается в том, что здесь для генерации исключения применяется пользовательский класс Exception, который содержит существенно большее количество информации о происшедшей ошибке: сообщение об ошибке, неверный аргумент и точное место, где произошла ошибка.
_________________
296 стр. Часть 5. Полезные особенности
«Встроенные макроопределения _FILE_ и _LINE_ представляют собой имя исходного файла и текущую строку в нём.»
[Советы]
Перехватчик исключения использует функцию-член display( ) для вывода сообщения об ошибке. Вывод программы выглядит следующим образом.
3! = 6
Ошибка:
Ошибка <Аргумент факториала отрицателен — значение равно -1> @С:/Documents/Dial/CppDummy/CustomExceptionClass.срр-46
Press any key to continue...
Класс Exception представляет собой базовый класс для сообщений об ошибках. Вы можете наследовать его и получить класс, который обеспечит более детальную информацию об ошибке. Например, я могу определить класс InvalidArgumentException, который в дополнение к прочему хранит значение неверного аргумента.
class InvalidArgumentException : public Exception
{
public :
InvalidArgumentException( int arg , char*pFile , int nLine )
: Exception( "Некорректный аргумент" , pFile , nLine )
{
invArg = arg ;
}
virtual void display( ostream& out )
{
Exception::display( out ) ;
out << "Аргумент " << invArg << endl ;
}
protected :
int invArg ;
}
Вызывающая функция автоматически обработает новое исключение, поскольку InvalidArgumentException ЯВЛЯЕТСЯ Exception, а функция-член display( ) — полиморфна.
_________________
297 стр. Глава 25. Обработка ошибок и исключения
Больше книг — больше знаний!
Заберите 20% скидку на все книги Литрес с нашим промокодом
ПОЛУЧИТЬ СКИДКУ