Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Программирование » Язык программирования C++. Пятое издание - Стенли Липпман

Язык программирования C++. Пятое издание - Стенли Липпман

Читать онлайн Язык программирования C++. Пятое издание - Стенли Липпман

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 260 261 262 263 264 265 266 267 268 ... 297
Перейти на страницу:

Собственные классы исключений применяются точно так же, как и классы стандартной библиотеки. Одна часть программы передает объект одного из этих классов, а другая получает и обрабатывает его, устраняя проблему. Например, для перегруженного оператора суммы класса Sales_item можно создать класс исключения isbn_mismatch, передаваемого в случае обнаружения ошибки несовпадения ISBN.

// передает исключение, если isbn объектов не совпадают

Sales_data&

Sales_data::operator+=(const Sales_data& rhs) {

 if (isbn() != rhs.isbn())

  throw isbn_mismatch("wrong isbns", isbn(), rhs.isbn());

 units_sold += rhs.units_sold;

 revenue += rhs.revenue;

 return *this;

}

Обнаружив эту ошибку, использующий оператор += код сможет передать соответствующее сообщение об ошибке и продолжить работу.

// применение исключения в приложении книжного магазина

Sales_data item1, item2, sum;

while (cin >> item1 >> item2) { // прочитать две транзакции

 try {

  sum = item1 + item2; // вычислить их сумму

  // использовать сумму

 } catch (const isbn_mismatch &e) {

  cerr << e.what() << ": left isbn(" << e.left

       << ") right isbn (" << e.right << ")" << endl;

 }

}

Упражнения раздела 18.1.5

Упражнение 18.9. Определите описанные в этом разделе классы исключений приложения книжного магазина и перепишите составной оператор присвоения класса Sales_data так, чтобы он передавал исключение.

Упражнение 18.10. Напишите программу, использующую оператор суммы класса Sales_data для объектов с разными ISBN. Напишите две версии программы: способную обрабатывать исключении и не обрабатывающую их. Сравните поведение программ, чтобы ознакомиться с тем, что происходит при отсутствии обработки исключения.

Упражнение 18.11. Почему так важно, чтобы функция what() не передавала исключений?

18.2. Пространства имен

В больших программах обычно используют библиотеки от независимых разработчиков. В таких библиотеках обычно определено множество глобальных имен классов, функций и шаблонов. Когда приложение использует библиотеки от многих разных поставщиков, некоторые из этих имен почти неизбежно совпадут. Библиотеки, помещающие имена в глобальное пространство имен, вызывают загромождение пространства имен (namespace pollution).

Традиционно программисты избегают загромождения пространства имен, используя для глобальных сущностей очень длинные имена, зачастую содержащие префикс, означающий библиотеку, в которой определено имя:

class cplusplus_primer_Query { ... };

string cplusplus_primer_make_plural(size_t, string&);

Это решение далеко от идеала: программистам неудобно писать и читать программы, использующие длинные имена.

Пространства имен (namespace) предоставляют намного более контролируемый механизм предотвращения конфликтов имени. Пространства имен разделяют глобальное пространство имен. Пространство имен — это область видимости. При определении имен библиотеки в пространстве имен, авторы (и пользователи) библиотеки могут избежать ограничений, присущих глобальным именам.

18.2.1. Определение пространств имен

Определение пространства имен начинается с ключевого слова namespace, сопровождаемого именем пространства имен. После имени пространства имен следуют заключенные в фигурные скобки объявления и определения. В пространство имен может быть помещено любое объявление, которое способно присутствовать в глобальной области видимости, включая классы, переменные (с инициализацией), функции (с их определениями), шаблоны и другие пространства имен.

namespace cplusplus_primer {

 class Sales_data { /* ... */};

 Sales_data operator+(const Sales_data&,

                      const Sales_data&);

 class Query { /* ... */ };

 class Query_base { /* ... */};

} // подобно блокам, пространства имен не завершаются точкой с запятой

Этот код определяет пространство имен cplusplus_primer с четырьмя членами: тремя классами и перегруженным оператором +.

Подобно другим именам, имя пространства имен должно быть уникальным в той области видимости, в которой оно определено. Пространства имен могут быть определены в глобальной области видимости или в другом пространстве имен. Они не могут быть определены в функциях или классах.

Область видимости пространства имен не заканчивается точкой с запятой.

Каждое пространство имен является областью видимости

Как и в случае любой области видимости, каждое имя в пространстве имен должно относиться к уникальной сущности в пределах данного пространства имен. Поскольку разные пространства имен вводят разные области видимости, в разных пространствах имен могут быть члены с одинаковым именем.

К именам, определенным в пространстве имен, другие члены данного пространства имен могут обращаться непосредственно, включая области видимости, вложенные в пределах этих членов. Код вне пространства имен должен указывать пространство имен, в котором определено имя:

cplusplus_primer::Query q =

 cplusplus_primer::Query("hello");

Если другое пространство имен (например, AddisonWesley) тоже содержит класс Query и этот класс необходимо использовать вместо определенного в пространстве имен cplusplus_primer, приведенный выше код придется изменить следующим образом:

AddisonWesley::Query q = AddisonWesley::Query("hello");

Пространства имен могут быть разобщены

Как упоминалось в разделе 16.5, в отличие от других областей видимости, пространство имен может быть определено в нескольких частях. Вот определение пространства имен:

namespace nsp {

 // объявления

}

Этот код определяет новое пространство имен nsp или добавляет члены к уже существующему. Если пространство имен nsp еще не определенно, то создается новое пространство имен с этим именем. В противном случае это определение открывает уже существующее пространство имен и добавляет в него новые объявления.

Тот факт, что определения пространств имен могут быть разобщены, позволяет составить пространство имен из отдельных файлов интерфейса и реализации. Таким образом, пространство имен может быть организовано таким же образом, как и определения собственных классов или функций.

• Члены пространства имен, являющиеся определениями классов, объявлениями функций и объектов, составляющих часть интерфейса класса, могут быть помещены в файлы заголовка. Эти заголовки могут быть подключены в те файлы, которые используют эти члены пространства имен.

• Определения членов пространства имен могут быть помещены в отдельные файлы исходного кода.

Организовав пространство имен таким образом, можно также удовлетворить требование, согласно которому различные сущности, включая не подлежащие встраиванию функции, статические переменные-члены, переменные и т.д., должны быть определены в программе только один раз. Это требование распространяется и на имена, определенные в пространстве имен. Отделив интерфейс и реализацию, можно гарантировать, что имена функций и другие имена будут определены только один раз и именно это объявление будет многократно использоваться впоследствии.

Для представления несвязанных типов в составных пространствах имен следует использовать отдельные файлы.

Определение пространства имен cplusplus_primer

Используя эту стратегию для отделения интерфейса от реализации, определим библиотеку cplusplus_primer в нескольких отдельных файлах. Объявления класса Sales_data и связанных с ним функций поместим в файл заголовка Sales_data.h, а таковые для класса Query (см. главу 15) — в заголовок Query.h и т.д. Соответствующие файлы реализации были бы в таких файлах, как Sales_data.cc и Query.cc:

// ---- Sales_data.h ----

// директивы #include должны быть перед открытием пространства имен

#include <string>

namespace cplusplus_primer {

 class Sales_data { /* ... */};

 Sales_data operator+(const Sales_data&,

                      const Sales_data&);

 // объявления остальных функций интерфейса класса Sales_data

}

// ---- Sales_data.cc ----

// все директивы #include перед открытием пространства имен

#include "Sales_data.h"

namespace cplusplus_primer {

 // определения членов класса Sales_data и перегруженных операторов

1 ... 260 261 262 263 264 265 266 267 268 ... 297
Перейти на страницу:
На этой странице вы можете бесплатно скачать Язык программирования C++. Пятое издание - Стенли Липпман торрент бесплатно.
Комментарии