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

на главную

Жанры

Шрифт:

Операцию доступа можно определить как

int amp; vector::operator[](int i) (* if(i«0 !! sz„=i) error(«vector index out of range“); // индекс выходит за границы вектора return v[i]; *)

Операция !! (ИЛИИЛИ) – это логическая операция ИЛИ. Ее правый операнд вычисляется только тогда, когда это необходимо, то есть если вычисление левого операнда дало ноль. Возращение ссылки обеспечивает то, что запись [] может использоваться с любой стороны операции присваивания:

v1[x] = v2[y];

Функция со странным именем ~vector – это деструктор, то есть функция, описанная для того, чтобы она неявно вызывалась,

когда объект класса выходит из области видимости. Деструктор класса C имеет имя ~C. Если его определить как

vector::~vector (* delete v; *)

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

1.12 Inline-подстановка

Если часто повторяется обращение к очень маленькой функции, то вы можете начать беспокоиться о стоимости вызова функции. Обращение к функции члену не дороже обращения к функции не члену с тем же числом параметров (надо помнить, что функция член всегда имеет хотя бы один параметр), и вызовы в функций в С++ примерно столь же эффективны, сколь и в любом языке. Однако для слишком маленьких функций может встать вопрос о накладных расходах на обращение. В этом случае можно рассмотреть возможность спецификации функции как inline-подставляемой. Если вы поступите таким образом, то компилятор сгенерирует для функции соответствующий код в мете ее вызова. Семантика вызова не изменяется. Если, например, size и elem inline-подставляемые, то

vector s(100); //... i = s.size; x = elem(i-1);

порождает код, эквивалентный

//... i = 100; x = s.v[i-1];

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

Вы можете указать, что вы хотите, чтобы функция была inline-подставляемой, поставив ключевое слово inline, или, для функции члена, просто включив определение функции в описание класса, как это сделано в предыдущем примере для size и elem.

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

1.13 Производные классы

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

class vec: public vector (* int low, high; public: vec(int,int);

int amp; elem(int); int amp; operator[](int); *);

Определение vec как :public vector

означает, в первую очередь, что vec – это vector. То есть, тип vec имеет (наследует) все свойства типа vector дополнительно к тем, что описаны специально для него. Говорят, что vector является базовым классом для vec, а о vec говорится, что он производный класс от vector. Класс vec модифицирует класс vector тем, что в нем задается другой конструктор, который требует от пользователя указывать две границы изменения индекса, а не длину, и имеются свои собственные функции доступа elem(int) и operator[](int). Функция elem класса vec легко выражается через elem класса vector: int amp; vec::elem(int i) (* return vector::elem(i-low); *)

Операция разрешения области видимости :: используется для того, чтобы не было бесконечной рекурсии обращения к vec::elem из нее самой. с помощью унарной операции :: можно ссылаться на нелокальные имена. Было бы разумно описать vec:: elem как inline, поскольку, скорее всего, эффективность существенна, но необязательно, неразумно и невозможно написать ее так, чтобы она непосредственно использовала закрытый член v класса vector. Функции производного класса не имеют специального доступа к закрытым членам его базового класса.

Конструктор можно написать так:

vec::vec(int lb, int hb) : (hb-lb+1) (* if (hb-lb«0) hb = lb; low = lb; high = hb; *)

Запись: (hb-lb+1) используется для определения списка параметров конструктора базового класса vector::vector. Этот конструктор вызывается перед телом vec::vec. Вот небольшой пример, который можно запустить, если скомпилировать его вместе с остальными описаниями vector:

#include «streams.h»

void error(char* p) (* cerr «„ p «« «\n“; // cerr – выходной поток сообщений об ошибках exit(1); *)

void vector::set_size(int) (* /* пустышка */ *)

int amp; vec::operator[](int i) (* if (i«low !! high„i) error(«vec index out of range“); // индекс vec за границами return elem(i); *)

main (* vector a(10); for (int i=0; i«a.size; i++) (* a[i] = i; cout „„ a[i] «« " "; *) cout «« «\n“; vec b(10,19); for (i=0; i«b.size; i++) b[i+10] = a[i]; for (i=0; i«b.size; i++) cout «« b[i+10] «« " "; cout «« «\n“; *)

Он выдает 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

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

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

1.14 Еще об операциях

Другое направление развития – снабдить вектора операциями:

class Vec : public vector (* public: Vec(int s) : (s) (**) Vec(Vec amp;); ~Vec (**) void operator=(Vec amp;); void operator*=(Vec amp;); void operator*=(int); //... *);

Обратите внимание на способ определения конструктора производного класса, Vec::Vec, когда он передает свой параметр конструктору базового класса vector::vector и больше не делает ничего. Это полезная парадигма. Операция присваивания перегружена, ее можно определить так:

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

Совок 2

Агарев Вадим
2. Совок
Фантастика:
альтернативная история
7.61
рейтинг книги
Совок 2

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

СД. Том 17

Клеванский Кирилл Сергеевич
17. Сердце дракона
Фантастика:
боевая фантастика
6.70
рейтинг книги
СД. Том 17

Первый пользователь. Книга 3

Сластин Артем
3. Первый пользователь
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Первый пользователь. Книга 3

Хочу тебя навсегда

Джокер Ольга
2. Люби меня
Любовные романы:
современные любовные романы
5.25
рейтинг книги
Хочу тебя навсегда

Адъютант

Демиров Леонид
2. Мания крафта
Фантастика:
фэнтези
6.43
рейтинг книги
Адъютант

Убивать, чтобы жить

Бор Жорж
1. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать, чтобы жить

Измена. Испорченная свадьба

Данич Дина
Любовные романы:
современные любовные романы
короткие любовные романы
5.00
рейтинг книги
Измена. Испорченная свадьба

Я – Орк. Том 3

Лисицин Евгений
3. Я — Орк
Фантастика:
юмористическое фэнтези
попаданцы
5.00
рейтинг книги
Я – Орк. Том 3

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Совок – 3

Агарев Вадим
3. Совок
Фантастика:
фэнтези
детективная фантастика
попаданцы
7.92
рейтинг книги
Совок – 3

С Д. Том 16

Клеванский Кирилл Сергеевич
16. Сердце дракона
Фантастика:
боевая фантастика
6.94
рейтинг книги
С Д. Том 16

Назад в СССР: 1986 Книга 5

Гаусс Максим
5. Спасти ЧАЭС
Фантастика:
попаданцы
альтернативная история
5.75
рейтинг книги
Назад в СССР: 1986 Книга 5

Ретроградный меркурий

Рам Янка
4. Серьёзные мальчики в форме
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Ретроградный меркурий