Самой интересной в этом списке является виртуальная функция what(), которая возвращает C-строку с текстовым описанием возбужденного исключения. Классы, производные от exception, могут заместить what() собственной версией, которая лучше характеризует объект-исключение.
Отметим, что все функции в определении класса exception имеют пустую спецификацию throw(), т.е. не возбуждают никаких исключений. Программа может манипулировать объектами-исключениями (к примеру, внутри catch-обработчиков типа exception), не опасаясь, что функции создания, копирования и уничтожения этих объектов возбудят исключения.
Помимо корневого exception, в стандартной библиотеке есть и другие классы, которые допустимо использовать в программе для извещения об ошибках, обычно подразделяемых на две больших категории: логические ошибки и ошибки времени выполнения.
Логические ошибки обусловлены нарушением внутренней логики программы, например логических предусловий или инвариантов класса. Предполагается, что их можно найти и предотвратить еще до начала выполнения программы. В стандартной библиотеке определены следующие такие ошибки:
namespace std {
class logic_error : public exception { // логическая ошибка
public:
explicit logic_error( const string &what_arg );
};
class invalid_argument : public logic_error { // неверный аргумент
public:
explicit invalid_argument( const string &what_arg );
};
class out_of_range : public logic_error { // вне диапазона
public:
explicit out_of_range( const string &what_arg );
};
class length_error : public logic_error { // неверная длина
public:
explicit length_error( const string &what_arg );
};
class domain_error : public logic_error { // вне допустимой области
public:
explicit domain_error( const string &what_arg );
};
}
Функция может возбудить исключение invalid_argument, если получит аргумент с некорректным значением; в конкретной ситуации, когда значение аргумента выходит за пределы допустимого диапазона, разрешается возбудить исключение out_of_range, а length_error используется для оповещения о попытке создать объект, длина которого превышает максимально возможную.
Ошибки времени выполнения, напротив, вызваны событием, с самой программой не связанным. Предполагается, что их нельзя обнаружить, пока программа не начала работать. В стандартной библиотеке определены следующие такие ошибки:
namespace std {
class runtime_error : public exception { // ошибка времени выполнения
public:
explicit runtime_error( const string &what_arg );
};
class range_error : public runtime_error { // ошибка диапазона
public:
explicit range_error( const string &what_arg );
};
class overflow_error : public runtime_error { // переполнение
public:
explicit overflow_error( const string &what_arg );
};
class underflow_error : public runtime_error { // потеря значимости
public:
explicit underflow_error( const string &what_arg );
};
}
Функция может возбудить исключение range_error, чтобы сообщить об ошибке во внутренних вычислениях. Исключение overflow_error говорит об ошибке арифметического переполнения, а underflow_error – о потере значимости.
Класс exception является базовым и для класса исключения bad_alloc, которое возбуждает оператор new(), когда ему не удается выделить запрошенный объем памяти (см. раздел 8.4), и для класса исключения bad_cast, возбуждаемого в ситуации, когда ссылочный вариант оператора dynamic_cast не может быть выполнен (см. раздел 19.1).
Переопределим оператор operator[] в шаблоне Array из раздела 16.12 так, чтобы он возбуждал исключение типа range_error, если индекс массива Array выходит за границы:
#include stdexcept
#include string
template class elemType
class Array {
public:
// ...
elemType& operator[]( int ix ) const
{
if ( ix 0 || ix = _size )
{
string eObj =
"ошибка: вне диапазона в ArrayelemType::operator[]() ";
throw out_of_range( eObj );
}
return _ia[ix];
}
// ...
private:
int _size;
elemType *_ia;
};
Для использования предопределенных классов исключений в программу необходимо включить заголовочный файл . Описание возбужденного исключения содержится в объекте eObj типа string. Эту информацию можно извлечь в обработчике с помощью функции-члена what():