- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Освой самостоятельно за 21 день - Джесс Либерти
Шрифт:
Интервал:
Закладка:
Передача объекта как значения
В листинге 15.3 показано, как создание одного объекта Employee приводит к вызову пяти конструкторов класса String. Листинг 15.4 — это еще один переписанный вариант программы. В нем нет дополнительных операторов вывода помимо представленных в листинге 15.1 (сейчас они разблокированы) и используется статическая переменная-член ConstructorCount, объявленная в классе String.
Как следует из объявления в листинге 15.1, значение переменной ConstructorCount увеличивается на единицу при каждом вызове конструктора класса String. В конце программы, представленной в листинге 15.4, объект Employee передается на печать сначала как ссылка, а затем как значение. Статическая переменная-член ConstructorCount отслеживает, сколько объектов класса String создается при разных способах передачи объекта Employee как параметра функции.
Примечание:Перед компиляцией этого листинга в программе листинга 15.1 дополнительно к тем строкам, которые были разблокированы для листинга 15.3, следует снять символы комментариев со строк 23, 39, 52, 64, 76 и 153.
Листинг 15.4. Передача объекта как значения
1: #include "String.hpp"
2:
3: class Employee
4: {
5:
6: public:
7: Employee();
8: Employee(char *, char *, char *, long);
9: ~Employee();
10: Employee(const Employee&);
11: Employee & operator= (const Employee &);
12:
13: const String & GetFirstName() const
14: { return itsFirstName; }
15: const String & GetLastName() const { return itsLastName; }
16: const String & GetAddress() const { return itsAddress;
17: long GetSalary() const { return itsSalary; }
18:
19: void SetFirstName(const String & fName)
20: { itsFirstName = fName; }
21: void SetLastName(const String & lName)
22: { itsLastName = lName; }
23: void SetAddress(const String & address)
24: { itsAddress = address; }
25: void SetSalary(long salary) { itsSalary = salary; }
26: private:
27: String itsFirstName;
28: String itsLastName;
29: String itsAddress;
30: long itsSalary;
31: };
32:
33: Employee::Employee();
34: itsFirstName(""),
35: itsLastName(""),
36: itsAddress(""),
37: itsSalary(0)
38: { }
39:
40: Employee::Employee(char * firstName, char * lastName,
41: char * address, long salary):
42: itsFirstName(firstName),
43: itsLastName(lastName),
44: itsAddress(address),
45: itsSalary(salary)
46: { }
47:
48: Employee::Employee(const Employee & rhs):
49: itsFirstName(rhs.GetFi rstName()),
50: itsLastName(rhs.GetLastName()),
51: itsAddress(rhs.GetAddress()),
52: itsSalary(rhs.GetSalary())
53: { }
54:
55: Employee::~Employee() { }
56:
57: Employee & Employee::operator= (const Employee & rhs)
58: {
59: if (this == &rhs)
60: return *this;
61:
62: itsFirstName = rhs.GetFirstName();
63: itsLastName = rhs.GetLastName();
64: itsAddress = rhs.GetAddress();
65: itsSalary = rhs.GetSalary();
66:
67: return *this;
68: }
69:
70: void PrintFunc(Employee);
71: void rPrintFuno(const Employee&):
72:
73: int main()
74: {
75: Employee Edie("Jane","Doe","1461 Shore Parkway", 20000);
76: Edie.SetSalary(20000);
77: Edie.SetFirstName("Edythe");
78: String LastName("Levine");
79: Edie.SetLastName(LastName); 80:
81: cout << "Constructor count: " ;
82: cout << String;:ConstruotorCount << endl;
83: rPrintFunc(Edie);
84: cout << "Constructor count: ";
85: cout << String::ConstructorCount << endl;
86: PrintFunc(Edie);
87: cout << "Constructor count: ";
88: cout << String::ConstructorCount << endl;
89: return 0;
90: }
91: void PrintFunc (Employee Edie)
92: {
93:
94: cout << "Name: ";
95: cout << Edie.GetFirstName().GetString();
96: cout << " " << Edie.GetLastName().GetString();
97: cout << ".nAddress: ";
98: cout << Edie.GetAddress().GetString();
99: cout << ".nSalary: " ;
100: cout << Edie.GetSalary();
101: cout << endl;
102:
103: }
104:
105: void rPrintFunc (const Employee& Edie)
106: {
107: cout << "Name: ";
108: cout << Edie.GetFirstName().GetString();
109: cout << " " << Edie.GetLastName().GetString();
110: cout << "nAddress: ";
111: cout << Edie.GetAddress().GetString();
112: cout << "nSalary: " ;
113: cout << Edie.GetSalary();
114: cout << endl;
115: }
Результат:
String(char*) constructor
String(char*) constructor
String(char*) constructor
String(char*) constructor
String destructor
String(char*) constructor
Constructor count: 5
Name: Edythe Levine
Address: 1461 Shore Parkway
Salary: 20000
Constructor count; 5
String(String&) constructor
String(String&) constructor
String(String&) constructor
Name: Edythe Levine
Address: 1461 Shore Parkway
Salary: 20000
String destructor
String destructor
String destructor
Constructor count: 8
String destructor
String destructor
String destructor
String destructor
Анализ: Как видно по данным, выводимым программой, в процессе создания одного объекта Employee создается пять объектов класса String. Когда объект Employee передается в функцию rPrintFunc() как ссылка, дополнительные объекты Employee не создаются. Соответственно не создаются и дополнительные объекты String. (Все они, кстати, также автоматически передаются как ссылки.)
Когда объект Employee передается в функцию PrintFunc() как значение, создается копия объекта Employee вместе с тремя объектами класса String (для этого используется конструктор-копировщик).
Различные пути передачи функциональности классу
В некоторых случаях одному классу необходимо передать некоторые свойства другого. Предположим, например, что вам необходимо создать класс каталога деталей PartsCatalog. На основе класса PartsCatalog предполагается создать коллекцию объектов, представляющую различные запчасти с уникальными номерами. В базе данных на основе класса PartsCatalog запрещается дублирование объектов, а для доступа к объекту необходимо указать его идентификационный номер.
Ранее, в обзоре за вторую неделю, уже был объявлен и детально проанализирован класс PartsList. Чтобы не начинать работу с нуля, можно взять этот класс за основу при объявлении класса PartsCatalog. Для этого можно вложить класс PartsList в класс PartsCatalog, чтобы затем делегировать классу PartsCatalog ответственность за поддержание связанного списка в класс PartsList.
Существует альтернативный путь. Можно произвести класс PartsCatalog от класса PartsList, таким образом унаследовав все свойства последнего. Помните однако, что открытое наследование (со спецификатором public) предполагает логическую принадлежность производного класса более общему базовому классу. Действительно ли в нашем случае класс PartsCatalog является частным проявлением класса PartList? Чтобы разобраться в этом, попробуйте ответить на ряд вопросов.
1. Содержит ли базовый класс PartsList методы, не применимые в классе PartsCatalog? Если да, то, вероятно, от открытого наследования лучше отказаться.
2. Будет ли один объект класса PartsCatalog соответствовать одному объекту класса PartsList? Если для создания объекта требуется не менее двух объектов PartsList, то, безусловно, необходимо применять вложение.
3. Обеспечит ли наследование от базового класса преимущества в работе благодаря использованию виртуальных функций или методов доступа к защищенным членам базового класса? В случае положительного ответа имеет смысл воспользоваться открытым или закрытым наследованием.
Ответив на приведенные выше вопросы, вы должны принять решение, использовать ли вам в программе открытое наследование, закрытое наследование (см. далее в этом занятии) или вложение. Познакомимся с некоторыми терминами, которые потребуются нам при дальнейшем обсуждении этой темы.
• Вложение — объект, относящийся к другому классу, используется в текущий класс.
• Делегирование — передача ответственности за выполнение специальных функций вложенному классу.
• Выполнение средствами класса — реализация специальных функций в классе за счет другого класса без использования открытого наследования.
Делегирование
Почему же класс PartsCatalog нельзя произвести от PartsList? Дело в том, что класс PartsCatalog должен обладать совершенно иными свойствами и ero невозможно представить как частную реализацию класса PartsList. Посмотрите, класс PartsList — это коллекция объектов, упорядоченная по возрастанию номеров, элементы которой могут повторяться. Класс PartsCatalog представляет неупорядоченную коллекцию уникальных объектов.
Конечно, при желании можно произвести класс PartsList от класса PartsList со спецификатором public, после чего соответствующим образом заместить функцию Insert() и оператор индексирования ([]). Однако такие действия крайне нелогичны и противоречат самой сути наследования. Вместо этого следует создать новый класс PartsCatalog, в котором нет оператора индексирования, не разрешается дублирование записей и перегружается operator+ для суммирования наборов записей. Функцию управления связанным списком оставим классу PartsList.
Попробуем сначала решить эту задачу путем вложения одного класса в другой с делегированием ответственности от класса классу, как показано в листинге 15.5.