Программирование. Принципы и практика использования C++ Исправленное издание, стр. 421
void f(int x){ try { Vector v(x); // может генерировать исключения // ... } catch (Bad_size bs) { cerr << "Вектор неправильного размера (" << bs.sz << ")\n"; // ... }}Для перехвата всех исключений можно использовать инструкцию
catch (...)try { // ...} catch (...) { // перехват всех исключений// ...}Как правило, лучше (проще, легче, надежнее) применять технологию RAII (“Resource Acquisition Is Initialization” — “выделение ресурсов — это инициализация”), чем использовать множество явных инструкций
trycatchИнструкция
throwthrow;try { // ...} catch (Some_exception& e) { // локальная очистка throw; // остальное сделает вызывающая функция}В качестве исключений можно использовать типы, определенные пользователем. В стандартной библиотеке определено несколько типов исключений, которые также можно использовать (раздел Б.2.1). Никогда не используйте в качестве исключений встроенные типы (это может сделать кто-то еще, и ваши исключения могут внести путаницу).
Когда генерируется исключение, система поддержки выполнения программ на языке С++ ищет вверх по стеку раздел
catchtryОбъект считается созданным в тот момент, когда заканчивает работу его конструктор. Он уничтожается либо в процессе раскрутки стека, либо при каком-либо ином выходе из своей области видимости. Это подразумевает, что частично созданные объекты (у которых некоторые члены или базовые объекты созданы, а некоторые — нет), массивы и переменные, находящиеся в области видимости, обрабатываются корректно. Подобъекты уничтожаются, если и только если они ранее были созданы. Не генерируйте исключение, передающееся из деструктора в вызывающий модуль. Иначе говоря, деструктор не должен давать сбой. Рассмотрим пример.
X::~X() { if (in_a_real_mess()) throw Mess(); } // никогда так // не делайте!Основная причина этого “драконовского” правила заключается в том, что если деструктор сгенерирует исключение (или сам не перехватит исключение) в процессе раскрутки стека, то мы не сможем узнать, какое исключение следует обработать. Целесообразно всеми силами избегать ситуаций, в которых выход из деструктора происходит с помощью генерирования исключения, поскольку не существует систематического способа создания правильного кода, в котором это может произойти. В частности, если это произойдет, не гарантируется правильная работа ни одной функции или класса из стандартной библиотеки.
A.15. Пространства имен
Пространство имен (namespace) объединяет связанные друг с другом объявления и предотвращает коллизию имен.
int a;namespace Foo { int a; void f(int i) { a+= i; // это переменная a из пространства имен Foo // (Foo::a) }}void f(int);int main(){ a = 7; // это глобальная переменная a (::a) f(2); // это глобальная функция f (::f) Foo::f(3); // это функция f из пространства имен Foo ::f(4); // это глобальная функция f (::f)}Имена можно явно уточнять именами их пространств имен (например,
Foo::f(3)::::f(2)Все имена в пространстве имен (например, в стандартном пространстве
stdusing namespace stdБудьте осторожны с директивой
usingusingusing Foo::g;g(2); // это функция g из пространства имен Foo (Foo::g)Более подробная информация о пространствах имен содержится в разделе 8.7.
A.16. Альтернативные имена
Для имени можно определить альтернативное имя (alias); иначе говоря, можно определить символическое имя, которое будет означать то же самое, что и имя, с которым оно связано (для большинства случаев употребления этого имени).