- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Освой самостоятельно за 21 день - Джесс Либерти
Шрифт:
Интервал:
Закладка:
Перегруженный оператор применяется в строке 171, где выполняется конкатенация двух строк.
Функции-друзья
Для объявления функции как друга класса используется ключевое слово friend, за которым следует объявление функции Это не предоставляет функции доступ к указателю this, но обеспечивает доступ ко всем закрытым и защищенным данным и функциям-членам.
Пример:
class PartNode
{ // ...
// сделаем функцию-член другого класса другом этого класса
friend void PartsList::Insert(Part*)
// сделаем другом глобальную функцию
friend int SomeFunction();
// ...
};
Перегрузка оператора вывода
Настало время снабдить наш класс String возможностью использовать объект cout для вывода своих данных так же, как при выводе данных базовых типов. До сих пор для вывода значения переменной-члена приходилось использовать следующее выражение:
cout << theString.GetString();
Неплохо было бы иметь возможность написать просто
cout << theString;
Для этого необходимо перегрузить функцию operator<<(). Более подробно использование потоков iostreams для вывода данных обсуждается на занятии 16. А в листинге 15.9 объявляется перегрузка функции operator<< как друга.
Листинг 15.8. Перегрузка operator<<()
1: #include <iostream.h>
2: #include <string.h>
3:
4: class String
5: {
6: public:
7: // конструкторы
8: String();
9: String(const char *const);
10: String(const String &);
11: ~String();
12:
13: // перегруженные операторы
14: char & operator[](int offset);
15: char operator[](int offset) const;
16: String operator+(const String&);
17: void operator+=(const String&);
18: String & operator= (const String &);
19: friend ostream& operator<<
20: (ostream& theStream,String& theString);
21: // Общие методы доступа
22: int GetLen()const { return itsLen; }
23: const char * GetString() const { return itsString; }
24:
25: private:
26: String (int); // закрытый конструктор
27: char * itsString;
28: unsigned short itsLen;
29: };
30:
31:
32: // конструктор, заданный no умолчанию, создает строку длиной 0 байт
33: String::String()
34: {
35: itsString = new char[1];
36: itsString[0] = ' ' ;
37: itsLen=0;
38: // cout << "tDefault string constructorn";
39: // ConstructorCount++;
40: }
41:
42: // закрытый конструктор, используемый только
43: // методами класса для создания новой строки
44: // указанного размера, заполненной значениями NULL.
45: String::String(int len)
46: {
47: itsString = new char[k:.H];
48: for (int i = 0; i<=len; i++)
49: itsString[i] = ' ';
50: itsLen=len;
51: // cout << "tString(int) constructorn";
52: // ConstructorCount++;
53: }
54:
55: // Преобразует массив символов в строку
56: String::String(const char * const cString)
57: {
58: itsLen = strlen(cString);
59: itsString = new char[itsLen+1];
60: for (int i = 0; i<itsLen; i++)
61: itsString[i] = cString[i];
62: itsString[itsLen]=' ';
63: // cout << "tString(char*) constructorn";
64: // ConstructorCount++;
65: }
66:
67: // конструктор-копировщик
68: String::String (const String & rhs)
69: {
70: itsLen=rhs.GetLen();
71: itsString = new char[itsLen+1];
72: for (int i = 0; i<itsLen;i++)
73: itsString[i] = rhs[i];
74: itsString[itsLen] = ' ';
75: // cout << "tString(String&) constructorn";
76: // ConstructorCount++;
77: }
78:
79: // деструктор освобождает занятую память
80: String::~String ()
81: {
82: delete [] itsString;
83: itsLen = 0;
84: // cout << "tString destructorn";
85: }
86:
87: // оператор равенства освобождает память, а затем
88: // копирует строку и размер
89: String& String::operator=(const String & rhs)
90: {
91: if (this == &rhs)
92: return *this;
93: delete [] itsString;
94: itsLen=rhs.GetLen();
95: itsString = new char[itsLen+1];
96: for (int i = 0; i<itsLen;i++)
97: itsString[i] = rhs[i];
98: itsString[itsLen] = ' ';
99: return *this;
100: // cout << "tString operator=n";
101: }
102:
103: // неконстантный оператор индексирования,
104: // возвращает ссылку на символ, который можно
105: // изменить!
106: char & String::operator[](int offset)
107: {
108: if (offset > itsLen)
109: return itsString[itsLen-1];
110: else
111: return itsString[offset];
112: }
113:
114: // константный оператор индексирования,
115: // используется для константных объектов (см. конструктор-копировщик!)
116: char String::operator[](int offset) const
117: {
118: if (offset > itsLen)
119: return itsString[itsLen-1];
120: else
121: return itsString[offset];
122: }
123:
124: // создает новую строку, добавляя текущую
125: // строку к rhs
126: String String::operator+(const String& rhs)
127: {
12S: int totalLen = itsLen + rhs.GetLen();
129: String temp(totalLen);
130: int i, j;
131: for (i = 0; i<itsLen; i++)
132: temp[i] = itsString[i];
133: for (j = 0; j<rhs.GetLen(); j++, i++)
134: temp[i] = rhs[];
135: temp[totalLen]=' ';
136: return temp;
137: }
138:
139: // изменяет текущую строку, ничего не возвращая
140: void String::operator+=(const String& rhs)
141: {
142: unsigned short rhsLen = rhs.GetLen();
143: unsigned short totalLen = itsLen + rhsLen;
144: String temp(totalLen);
145: int i, j;
146: for (i = 0; i<itsLen; i++)
147: temp[i] = itsString[i];
148: for (j = 0, i = 0; j<rhs.GetLen(); j++, i++)
149: temp[i] = rhs[i-itsLen];
150: temp[totalLen]=' ' ;
151: *this = temp;
152: }
153:
154: // int String::ConstructorCount =
155: ostream& operator<< ( ostream& theStream,String& theString)
156: {
157: theStream << theString.itsString; 158: return theStream;
159: }
160:
161: int main()
162: {
163: String theString("Hello world.");
164: cout << theString;
165: return 0;
166: }
Результат:
Hello world.
Анализ: В строке 19 operator<< объявляется как функция-друг, которая принимает ссылки на ostream и String и возвращает ссылку на ostream. Обратите внимание, что она не является функцией-членом класса String. Поскольку эта функция возвращает ссылку на ostream, можно конкатенировать вызовы operator<< следующим образом:
cout << "myAge: " << itsAge << " years. ";
Выполнение этой функции-друга представлено строками 155—159. Основное назначение функции состоит в том, чтобы скрыть детали процедуры передачи строки в iostream. Больше ничего и не требуется. Более подробно о функции ввода и перегрузке operator>> вы узнаете на следующем занятии.
Резюме
Сегодня вы узнали, как делегировать ответственность за выполнение специальных задач вложенным объектам, а также выполнять один класс в пределах другого с помощью вложения или открытого наследования. Основное ограничение вложения — отсутствие у нового класса доступа к защищенным членам вложенного класса и возможности замещения функций-членов вложенного объекта. Вложение гораздо проще в использовании, чем закрытое наследование, поэтому по возможности следует применять этот подход.
Вы также узнали, как объявлять классы и функции-друзьями другого класса. Объявление функции друга позволяет перегрузить оператор ввода таким образом, что появляется возможность использовать объект cout в пользовательском классе точно так же, как в стандартных встроенных классах.
Напомним, что открытое наследования определяет производный класс как уточнение базового класса; вложение подразумевает обладание одним классом объектами другого класса, а закрытое наследование состоит в выполнении одного класса средствами другого класса. Делегирование ответственности реализуется либо вложением, либо закрытым наследованием, хотя первое предпочтительнее.
Вопросы и ответы
Почему так важно разбираться в особенностях отношений между классами при выборе различных подходов установки взаимосвязей между ними?
Язык программирования C++ создавался специально для разработки объектно-ориентированных программ. Характерной особенностью объектно-ориентированного программирования является моделирование в программе реальных отношений между объектами и явлениями окружающего мира, причем при выборе подходов программирования следует учитывать особенности этих отношений, чтобы максимально точно смоделировать реальность.
Почему вложение предпочтительнее закрытого наследования?
Современное программирование — это разрешение противоречий между достижением максимальной точности моделирования событий и предупреждением чрезвычайного усложнения программ. Поэтому чем больше объектов программы будут использоваться как "черные ящики", тем меньше всевозможных параметров нужно отслеживать при отладке или модернизации программы. Методы вложенных классов скрыты от пользователей, что нельзя сказать о закрытом наследовании.
Почему бы не описать все классы, объекты которых используются в других классах, друзьями этих классов?