* ГЛАВА 5. КЛАССЫ
"Эти типы не абстрактные, они столь же реальны,
как int и float"
- Даг Макилрой
В этой главе описываются возможности определения новых типов,
для которых доступ к данным ограничен заданным множеством
функций, осуществляющих его. Объясняется, как можно использовать
члены структуры данных, как ее защищать, инициализировать и,
наконец, уничтожать. В примерах приведены простые классы для
управления таблицей имен, работы со стеком, множеством и
реализации дискриминирующего (т.е. надежного) объединения.
Следующие три главы завершают описание возможностей С++ для
построения новых типов, и в них содержится больше интересных
примеров.
5.1 Введение и краткий обзор
Понятие класса, которому посвящена эта и три следующих главы, служит
в С++ для того, чтобы дать программисту инструмент построения новых
типов. Ими пользоваться не менее удобно, чем встроенными.
В идеале использование определенного пользователем типа не должно
отличаться от использования встроенных типов. Различия возможны только
в способе построения.
Тип есть вполне конкретное представление некоторого понятия.
Например, в С++ тип float с операциями +, -, * и т.д. является
хотя и ограниченным, но конкретным представлением математического
понятия вещественного числа. Новый тип создается для того, чтобы
стать специальным и конкретным представлением понятия, которое не находит
прямого и естественного отражения среди встроенных типов. Например,
в программе из области телефонной связи можно ввести тип
trunk_module (линия-связи), в видеоигре - тип explosion (взрыв),
а в программе, обрабатывающей текст, - тип list_of_paragraphs
(список-параграфов). Обычно проще понимать и изменять программу,
в которой типы хорошо представляют используемые в задаче понятия.
Удачно подобранное множество пользовательских типов делает программу
более ясной. Оно позволяет транслятору обнаруживать недопустимое
использование объектов, которое в противном случае останется
невыявленным до отладки программы.
Главное в определении нового типа - это отделить несущественные
детали реализации (например, расположение данных в объекте нового
типа) от тех его характеристик, которые существенны для правильного
его использования (например, полный список функций, имеющих доступ
к данным). Такое разделение обеспечивается тем, что вся работа со
структурой данных и внутрение, служебные операции над нею доступны
только через специальный интерфейс (через "одно горло").
Глава состоит из четырех частей:
$$5.2 Классы и члены. Здесь вводится основное понятие
пользовательского типа, называемого классом. Доступ к объектам
класса может ограничиваться множеством функций, описания
которых входят в описание класса. Эти функции называются
функциями-членами и друзьями. Для создания объектов класса
используются специальные функции-члены, называемые
конструкторами. Можно описать специальную функцию-член
для удаления объектов класса при его уничтожении. Такая
функция называется деструктором.
$$5.3 Интерфейсы и реализации. Здесь приводятся два примера
разработки, реализации и использования классов.
$$5.4 Дополнительные свойства классов. Здесь приводится много
дополнительных подробностей о классах. Показано, как
функции, не являющейся членом класса, предоставить доступ
к его частной части. Такую функцию называют другом класса.
Вводятся понятия статических членов класса и указателей
на члены класса. Здесь же показано, как определить
дискриминирующее объединение.
$$5.5 Конструкторы и деструкторы. Объект может создаваться как
автоматический, статический или как объект в свободной
памяти. Кроме того, объект может быть членом некоторого
агрегата (массива или другого класса), который тоже
можно размещать одним из этих трех способов. Подробно
объясняется использование конструкторов и деструкторов,
описывается применение определяемых пользователем функций
размещения в свободной памяти и функций освобождения памяти.
5.2 Классы и члены
Класс - это пользовательский тип. Этот раздел знакомит с основными
средствами определения класса, создания его объектов, работы с
такими объектами и, наконец, удаления этих объектов после
использования.
Посмотрим, как можно представить в языке понятие даты, используя
для этого тип структуры и набор функций, работающих с переменными
этого типа:
struct date { int month, day, year; };
date today;
void set_date(date*, int, int, int);
void next_date(date*);
void print_date(const date*);
// ...
Никакой явной связи между функциями и структурой date нет. Ее можно
установить, если описать функции как члены структуры:
struct date {
int month, day, year;
void set(int, int, int);
void get(int*, int* int*);
void next();
void print();
};
Описанные таким образом функции называются функциями-членами. Их можно
вызывать только через переменные соответствующего типа, используя
стандартную запись обращения к члену структуры:
date today;
date my_birthday;
void f()
{
my_birthday.set(30,12,1950);
today.set(18,1,1991);
my_birthday.print();
today.next();
}
Поскольку разные структуры могут иметь функции-члены с одинаковыми
именами, при определении функции-члена нужно указывать имя структуры:
void date::next()
{
if (++day > 28 ) {
// здесь сложный вариант
}
}
В теле функции-члена имена членов можно использовать без указания
имени объекта. В таком случае имя относится к члену того объекта,
для которого была вызвана функция.
Достарыңызбен бөлісу: |