Категории
Самые читаемые

C++ - Страустрап Бьярн

Читать онлайн C++ - Страустрап Бьярн

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 27 28 29 30 31 32 33 34 35 ... 70
Перейти на страницу:

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

Эта глава состоит из четырех практически отдельных чатей:

#5.2 Классы и Члены. Этот раздел знакомит с основным понятием типа, определяемого пользователем, который называеся класс (class). Доступ к объектам класса может ограничваться набором функций, которые описаны как часть этого класа. Такие функции называются функциями членами. Объекты класса создаются и инициализируются функциями членами, спецально для этой цели описанными. Эти функции называются контрукторами. Функция член может быть специальным образом опсана для «очистки» каждого классового объекта при его уничтожении. Такая функция называется деструктором.

#5.3 Интерфейсы и Реализации. В этом разделе приводится два примера того, как класс проектируется, реализуется и ипользуется.

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

#5.5 Конструкторы и Деструкторы. Объект может создаватся как автоматический, статический или как объект в свободной памяти. Объект может также быть членом некоторой совокупности (типа вектора или класса), которая в свою очередь может рамещаться одним из этих трех способов. Довольно подробно обясняется использование конструкторов и деструкторов.

5.2 Классы и члены

Класс – это определяемый пользователем тип. Этот раздел знакомит с основными средствами определения класса, создания объекта класса, работы с такими объектами и, наконец, уничтжения таких объектов после использования.

5.2.1 Функции члены

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

struct date (* int month, day, year; *); // дата: месяц, день, год *) date today; void set_date(date*, int, int, int); void next_date(date*); void print_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_burthday; // мой день рождения

void f() (* my_burthday.set(30,12,1950); today.set(18,1,1985);

my_burthday.print();

today.next(); *)

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

void date::next() (* if ( ++day » 28 ) (* // делает сложную часть работы *) *)

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

5.2.2 Классы

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

class date (* int month, day, year; public: void set(int, int, int); void get(int*, int*, int*); void next(); void print(); *);

Метка public: делит тело класса на две части. Имена в первой, закрытой части, могут использоваться только функциями членами. Вторая, открытая часть, составляет интерфейс к обекту класса. Struct – это просто class, у которого все члены классы открытые, поэтому функции члены определяются и исползуются точно так же, как в предыдущем случае. Например:

void date::ptinr() // печатает в записи, принятой в США (* cout «« month «« "/" «« day «« "/" year; *)

Однако функции не члены отгорожены от использования зарытых членов класса date. Например:

void backdate() (* today.day–; // ошибка *)

В том, что доступ к структуре данных ограничен явно опсанным списком функций, есть несколько преимуществ. Любая ошибка, которая приводит к тому, что дата принимает недопутимое значение (например, Декабрь 36, 1985) должна быть вывана кодом функции члена, поэтому первая стадия отладки, лкализация, выполняется еще до того, как программа будет запущена. Это частный случай общего утверждения, что любое изменение в поведении типа date может и должно вызываться именениями в его членах. Другое преимущество – это то, что птенциальному пользователю такого типа нужно будет только унать определение функций членов, чтобы научиться им пользоваться.

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

5.2.3 Ссылки на себя

В функции члене на члены объекта, для которого она была вызвана, можно ссылаться непосредственно. Например:

class x (* int m; public: int readm() (* return m; *) *);

x aa; x bb;

void f() (* int a = aa.readm(); int b = bb.readm(); // ... *)

В первом вызове члена member() m относится к aa.m, а во втором – к bb.m.

Указатель на объект, для которого вызвана функция член, является скрытым параметром функции. На этот неявный параметр можно ссылаться явно как на this. В каждой функции класса x указатель this неявно описан как

x* this;

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

class x (* int m; public: int readm() (* return this-»m; *) *);

При ссылке на члены использование this излишне. Главным образом this используется при написании функций членов, котрые манипулируют непосредственно указателями. Типичный пример этого – функция, вставляющая звено в дважды связанный список:

class dlink (* dlink* pre; // предшествующий dlink* suc; // следующий public: void append(dlink*); // ... *);

void dlink::append(dlink* p) (* p-»suc = suc; // то есть, p-»suc = this-»suc p-»pre = this; // явное использование this suc-»pre = p; // то есть, this-»suc-»pre = p suc = p; // то есть, this-»suc = p *)

dlink* list_head;

void f(dlink*a, dlink *b) (* // ... list_head-»append(a); list_head-»append(b); *)

Цепочки такой общей природы являются основой для списквых классов, которые описываются в Главе 7. Чтобы присоеднить звено к списку необходимо обновить объекты, на которые указывают указатели this, pre и suc (текущий, предыдущий и последующий). Все они типа dlink, поэтому функция член dlink::append() имеет к ним доступ. Единицей защиты в С++ яляется class, а не отдельный объект класса.

5.2.4 Инициализация

Использование для обеспечения инициализации объекта класса функций вроде set_date() (установить дату) неэлегантно и чревато ошибками. Поскольку нигде не утверждается, что обект должен быть инициализирован, то программист может забыть это сделать, или (что приводит, как правило, к столь же рарушительным последствиям) сделать это дважды. Есть более хроший подход: дать возможность программисту описать функцию, явно предназначенную для инициализации объектов. Поскольку такая функция конструирует значения данного типа, она назывется конструктором. Конструктор распознается по тому, что имеет то же имя, что и сам класс. Например:

1 ... 27 28 29 30 31 32 33 34 35 ... 70
Перейти на страницу:
На этой странице вы можете бесплатно скачать C++ - Страустрап Бьярн торрент бесплатно.
Комментарии