- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Производный класс может предоставить объявление using только для тех имен, доступ к которым разрешен.
Уровни защиты наследования по умолчаниюВ разделе 7.2 упоминалось о том, что у классов, определенных с использованием ключевых слов struct, и class разные спецификаторы доступа по умолчанию. Точно так же заданный по умолчанию спецификатор наследования зависит от ключевого слова, используемого при определении производного класса. По умолчанию у производного класса, определенного с ключевым словом class, будет закрытое наследование (private inheritance), а с ключевым словом struct — открытое (public inheritance):
class Base { /* ... */ };
struct D1 : Base { /* ... */ }; // открытое наследование по умолчанию
class D2 : Base { /* ... */ }; // закрытое наследование по умолчанию
Весьма распространенно заблуждение, что между классами и структурами есть иные, более глубокие различия. Единственное различие — заданные по умолчанию спецификаторы доступа для членов и наследования. Никаких других различий нет.
Для закрытого наследования производный класс должен быть явно определен как private, не следует полагаться на поведение по умолчанию. Это ясно дает понять, что закрытое наследование применено преднамеренно, а не по оплошности.
Упражнения раздела 15.5Упражнение 15.18. С учетом классов Base и производных от него, и типов объектов, приведенных в комментариях, укажите, какие из следующих присвоений допустимы. Объясните, почему некорректны недопустимые.
Base *p = &d1; // d1 имеет тип Pub_Derv
p = &d2; // d2 имеет тип Priv_Derv
p = &d3; // d3 имеет тип Prot_Derv
p = &dd1; // dd1 имеет тип Derived_from_Public
p = &dd2; // dd2 имеет тип Derived_from_Private
p = &dd3; // dd3 имеет тип Derived_from_Protected
Упражнение 15.19. Предположим, у каждого из классов: Base и производных от него, есть функция-член в формате
void memfcn(Base &b) { b = *this; }
Укажите, была ли эта функция допустима для каждого класса.
Упражнение 15.20. Напишите код проверки ответов на предыдущие два упражнения.
Упражнение 15.21. Выберите одну из следующих общих абстракций, содержащих семейство типов (или любую собственную). Организуйте типы в иерархию наследования.
(a) Форматы графических файлов (например: gif, tiff, jpeg, bmp)
(b) Геометрические примитивы (например: box, circle, sphere, cone)
(c) Типы языка С++ (например: class, function, member function)
Упражнение 15.22. Укажите имена некоторых из наиболее вероятных виртуальных функций, а также открытых и защищенных членов для класса, выбранного в предыдущем упражнении.
15.6. Область видимости класса при наследовании
Каждый класс определяет собственную область видимости (scope) (см. раздел 7.4), в рамках которой определены его члены. При наследовании область видимости производного класса (см. раздел 2.2.4) вкладывается в области видимости его базовых классов. Если имя не найдено в области видимости производного класса, поиск его определения продолжается в областях видимости базовых классов.
Тот факт, что область видимости производного класса вложена в область видимости его базовых классов, может быть удивителен. В конце концов, базовые и производные классы определяются в разных частях текста программы. Но именно это иерархическое вложение областей видимости класса позволяет членам производного класса использовать члены его базового класса, как будто они являются частью производного класса. Рассмотрим пример:
Bulk_quote bulk;
cout << bulk.isbn();
В этом коде поиск определения имени isbn() осуществляется следующим образом.
• Поскольку вызывается функция isbn() объекта типа Bulk_quote, поиск начинается в классе Bulk_quote. В этом классе имя isbn() не найдено.
• Поскольку класс Bulk_quote происходит от класса Disc_quote, в нем и продолжается поиск. Имя все еще не найдено.
• Поскольку класс Disc_quote происходит от класса Quote, поиск продолжается в нем. В этом классе находится определение имени isbn(); таким образом, вызов isbn() распознается как вызов функции isbn() класса Quote.
Поиск имен осуществляется во время компиляцииСтатический тип (см. раздел 15.2.3) объекта, ссылки или указателя определяет, какие члены этого объекта будут видимы. Даже когда статический и динамический типы отличаются (это бывает в случае, когда используется ссылка или указатель на базовый класс), именно статический тип определяет применимые члены. Например, в класс Disc_quote можно было бы добавить функцию-член, которая возвращает пару (тип pair) (см. раздел 11.2.3), содержащую минимальное (или максимальное) количество и цену со скидкой.
class Disc_quote : public Quote {
public:
std::pair<size_t, double> discount_policy() const
{ return {quantity, discount}; }
// другие члены как прежде
};
Функцию discount_policy() можно использовать только через объект, указатель, или ссылку на тип Disc_quote, или класс, производный от него:
Bulk_quote bulk;
Bulk_quote *bulkP = &bulk; // статический и динамический типы совпадают
Quote *itemP = &bulk; // статический и динамический типы отличаются
bulkP->discount_policy(); // ok: bulkP имеет тип Bulk_quote*
itemP->discount_policy(); // ошибка: itemP имеет тип Quote*
Хотя объект bulk имеет функцию-член discount_policy(), она недоступна через указатель itemP. Тип itemP — указатель на тип Quote, а это значит, что поиск имени discount_policy() начнется в классе Quote. У класса Quote нет члена по имени discount_policy(), поэтому вызов этой функции-члена объекта, ссылки или указателя на тип Quote невозможен.
Конфликт имен и наследованиеКак и любая другая, область видимости производного класса позволяет повторно использовать имя, определенное в его прямом или косвенном базовом классе. Как обычно, имена, определенные во внутренней области видимости (например, в производном классе), скрывают имена во внешней области видимости (например, в базовом классе) (см. раздел 2.2.4):
struct Base {
Base() : mem(0) { }
protected:
int mem;
};
struct Derived : Base {
Derived(int i): mem(i) { } // Derived::mem инициализируется i
// Base::mem инициализируется по умолчанию
int get_mem() { return mem; } // возвращает Derived::mem
protected:
int mem; // скрывает mem в Base
};
Ссылка на переменную mem в функции get_mem() распознается как имя в классе Derived. Таким образом, код
Derived d(42);
cout << d.get_mem() << endl; // выводит 42
выведет значение 42.
Член производного класса, имя которого совпадает с именем члена базового класса, скрывает член базового класса и предотвращает прямой доступ к нему.
Применение оператора области видимости для доступа к скрытым членамДля доступа к скрытому члену базового класса можно использовать оператор области видимости.
struct Derived : Base {
int get_base_mem() { return Base::mem; }
};
Оператор области видимости изменяет нормальный порядок поиска и заставляет компилятор начинать поиск имени mem с класса Base. Если бы код выше был выполнен с этой версией класса Derived, то результатом вызова d.get_mem() был бы 0.
Кроме переопределения унаследованных виртуальных функций, производный класс обычно не должен повторно использовать имена, определенные в его базовом классе.
Ключевая концепция. Поиск имени и наследованиеДля понимания наследования в языке С++ крайне важно знать, как распознаются вызовы функций. Процесс распознавания вызова p->mem() (или obj.mem()) проходит в четыре этапа.
• Сначала определяется статический тип объекта p (или obj). Поскольку это вызов члена класса, тип будет классом.
• Поиск имени mem осуществляется в классе, который соответствует статическому типу объекта p (или obj). Если функция mem() не найдена, поиск продолжается в прямом базовом классе и далее по цепи классов, пока имя mem не будет найдено или пока не будет осмотрен последний класс. Если функция mem() не будет найдена ни в самом классе, ни в его базовых классах, вызов откомпилирован не будет.

