Чтение онлайн

на главную

Жанры

Шрифт:

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

date d = today; // инициализация посредством присваивания

По существу, имеется конструктор по умолчанию, опредленный как побитовая копия объекта того же класса. Если для класса X такой конструктор по умолчанию нежелателен, его моно переопределить конструктором с именем X(X amp;). Это будет осуждаться в #6.6.

5.2.5 Очистка

Определяемый

пользователем тип чаще имеет, чем не имеет, конструктор, который обеспечивает надлежащую инициализацию. Для многих типов также требуется обратное действие, деструктор, чтобы обеспечить соответствующую очистку объектов этого типа. Имя деструктора для класса X есть ~X («дополнение конструктора»). В частности, многие типы используют некоторый объем памяти из свободной памяти (см. #3.2.6), который выдляется конструктором и освобождается деструктором. Вот, наример, традиционный стековый тип, из которого для краткости полностью выброшена обработка ошибок:

class char_stack (* int size; char* top; char* s; public: char_stack(int sz) (* top=s=new char[size=sz]; *) ~char_stack (* delete s; *) // деструктор void push(char c) (* *top++ = c; *) char pop (* return *–top;*) *)

Когда char_stack выходит из области видимости, вызываеся деструктор:

void f (* char_stack s1(100); char_stack s2(200); s1.push('a'); s2.push(s1.pop); char ch = s2.pop; cout «„ chr(ch) «« «\n“; *)

Когда вызывается f, конструктор char_stack вызывается для s1, чтобы выделить вектор из 100 символов, и для s2, чтбы выделить вектор из 200 символов. При возврате из f эти два вектора будут освобождены.

5.2.6 Inline

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

Чтобы справиться с этой проблемой, был разработан аппрат inline-функций. Функция, определенная (а не просто опсанная) в описании класса, считается inline. Это значит, наример, что в функциях, которые используют приведенные выше char_stack, нет никаких вызовов функций кроме тех, которые используются для реализации операций вывода! Другими словами, нет никаких затрат времени выполнения, которые стоит принмать во внимание при разработке класса. Любое, даже самое мленькое действие, можно задать эффективно. Это утверждение снимает аргумент, который чаще всего приводят чаще всего в пользу открытых членов данных.

Функцию член можно также описать как inline вне описания класса. Например: char char_stack (* int size; char* top;

char* s; public: char pop; // ... *);

inline char char_stack::pop (* return *–top; *)

5.3

Интерфейсы и реализации

Что представляет собой хороший класс? Нечто, имеющее нбольшое и хорошо определенное множество действий. Нечто, что можно рассматривать как «черный ящик», которым манипулируют только посредством этого множества действий. Нечто, чье фатическое представление можно любым мыслимым способом измнить, не повлияв на способ использования множества действий. Нечто, чего можно хотеть иметь больше одного.

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

Сокрытие данных и продуманный интерфейс может дать коцепция модуля (см. например #4.4: файлы как модули). Класс, однако, является типом. Чтобы использовать его, необходимо создать объекты этого класса, и таких объектов можно создвать столько, сколько нужно. Модуль же сам является объектом. Чтобы использовать его, его надо только инициализировать, и таких объектов ровно один.

5.3.1 Альтернативные реализации

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

struct name (* char* string; char* next; double value; *);

Вот вариант класса table:

// файл table.h

class table (* name* tbl; public: table (* tbl = 0; *)

name* look(char*, int = 0); name* insert(char* s) (* return look(s,1); *) *);

Эта таблица отличается от той, которая определена в Глве 3 тем, что это настоящий тип. Можно описать более чем одну

table, можно иметь указатель на table и т.д. Например:

#include «table.h»

table globals; table keywords; table* locals;

main (* locals = new table; // ... *)

Вот реализация table::look, которая использует линеный поиск в связанном списке имен name в таблице:

#include «string.h»

name* table::look(char* p, int ins) (* for (name* n = tbl; n; n=n-»next) if (strcmp(p,n-»string) == 0) return n;

if (ins == 0) error(«имя не найдено»);

name* nn = new name; nn-»string = new char[strlen(p)+1]; strcpy(nn-»string,p); nn-»value = 1; nn-»next = tbl; tbl = nn; return nn; *)

Теперь рассмотрим класс table, усовершенствованный таким образом, чтобы использовать хэшированный просмотр, как это делалось в примере с настольным калькулятором. Сделать это труднее из-за того ограничения, что уже написанные программы, в которых использовалась только что определенная версия класа table, должны оставаться верными без изменений:

Поделиться:
Популярные книги

Черный Маг Императора 13

Герда Александр
13. Черный маг императора
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 13

Последняя Арена 4

Греков Сергей
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 4

Маяк надежды

Кас Маркус
5. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Маяк надежды

Великий перелом

Ланцов Михаил Алексеевич
2. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Великий перелом

Сопротивляйся мне

Вечная Ольга
3. Порочная власть
Любовные романы:
современные любовные романы
эро литература
6.00
рейтинг книги
Сопротивляйся мне

Инквизитор Тьмы 2

Шмаков Алексей Семенович
2. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Инквизитор Тьмы 2

Мастер Разума V

Кронос Александр
5. Мастер Разума
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Мастер Разума V

Бандит 2

Щепетнов Евгений Владимирович
2. Петр Синельников
Фантастика:
боевая фантастика
5.73
рейтинг книги
Бандит 2

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Падение Твердыни

Распопов Дмитрий Викторович
6. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Падение Твердыни

"Дальние горизонты. Дух". Компиляция. Книги 1-25

Усманов Хайдарали
Собрание сочинений
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Дальние горизонты. Дух. Компиляция. Книги 1-25

Ох уж этот Мин Джин Хо 2

Кронос Александр
2. Мин Джин Хо
Фантастика:
попаданцы
5.00
рейтинг книги
Ох уж этот Мин Джин Хо 2

Энфис 6

Кронос Александр
6. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 6