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

на главную - закладки

Жанры

Шрифт:

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

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, должны оставаться верными без изменений:

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

Мастер 9

Чащин Валерий
9. Мастер
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Мастер 9

Технарь

Муравьёв Константин Николаевич
1. Технарь
Фантастика:
космическая фантастика
попаданцы
7.13
рейтинг книги
Технарь

Путь Шедара

Кораблев Родион
4. Другая сторона
Фантастика:
боевая фантастика
6.83
рейтинг книги
Путь Шедара

Искатель 1

Шиленко Сергей
1. Валинор
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Искатель 1

Точка Бифуркации V

Смит Дейлор
5. ТБ
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Точка Бифуркации V

Звездная Кровь. Изгой VII

Елисеев Алексей Станиславович
7. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
технофэнтези
рпг
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Изгой VII

Архил...?

Кожевников Павел
1. Архил...?
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Архил...?

Сотник

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

Система Возвышения. (цикл 1-8) - Николай Раздоров

Раздоров Николай
Система Возвышения
Фантастика:
боевая фантастика
4.65
рейтинг книги
Система Возвышения. (цикл 1-8) - Николай Раздоров

#Бояръ-Аниме. Газлайтер. Том 24

Володин Григорий Григорьевич
24. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 24

Страна Арманьяк. Компиляция. Книги 1-7

Башибузук Александр
Страна Арманьяк
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Страна Арманьяк. Компиляция. Книги 1-7

Наследие Маозари 7

Панежин Евгений
7. Наследие Маозари
Фантастика:
боевая фантастика
юмористическое фэнтези
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 7

Наследие Маозари 4

Панежин Евгений
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Наследие Маозари 4

Трактир «Разбитые надежды»

Свержин Владимир Игоревич
1. Трактир "Разбитые надежды"
Фантастика:
боевая фантастика
7.69
рейтинг книги
Трактир «Разбитые надежды»