- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
• Вывод. Это способ построения одного класса из другого так, чтобы новый класс можно было использовать вместо исходного. Например, класс Circle является производным от класса Shape, иначе говоря, класс Circle является разновидностью класса Shape или класс Shape является базовым по отношению к классу Circle. Производный класс (в данном случае Circle) получает все члены базового класса (в данном случае Shape) в дополнение к своим собственным. Это свойство часто называют наследованием (inheritance), потому что производный класс наследует все члены базового класса. Иногда производный класс называют подклассом (subclass), а базовый — суперклассом (superclass).
• Виртуальные функции. В языке С++ можно определить функцию в базовом классе и функцию в производном классе с точно таким же именем и типами аргументов, чтобы при вызове пользователем функции базового класса на самом деле вызывалась функция из производного класса. Например, когда класс Window вызывает функцию draw_lines() из класса Circle, выполняется именно функция draw_lines() из класса Circle, а не функция draw_lines() из класса Shape. Это свойство часто называют динамическим полиморфизмом (run-time polymorphism) или динамической диспетчеризацией (run-time dispatch), потому что вызываемые функции определяются на этапе выполнения программы по типу объекта, из которого они вызываются.
• Закрытые и защищенные члены. Мы закрыли детали реализации наших классов, чтоб защитить их от непосредственного доступа, который может затруднить сопровождение программы. Это свойство часто называют инкапсуляцией (encapsulation).
Наследование, динамический полиморфизм и инкапсуляция — наиболее распространенные характеристики объектно-ориентированного программирования (object-oriented programming). Таким образом, язык C++ непосредственно поддерживает объектно-ориентированное программирование наряду с другими стилями программирования. Например, в главах 20-21 мы увидим, как язык C++ поддерживает обобщенное программирование. Язык C++ позаимствовал эти ключевые механизмы из языка Simula67, первого языка, непосредственно поддерживавшего объектно-ориентированное программирование (подробно об этом речь пойдет в главе 22).
Довольно много технической терминологии! Но что все это значит? И как на самом деле эти механизмы работают? Давайте сначала нарисуем простую диаграмму наших классов графического интерфейса, показав их отношения наследования.
Стрелки направлены от производного класса к базовому. Такие диаграммы помогают визуализировать отношения между классами и часто украшают доски программистов. По сравнению с коммерческими пакетами эта иерархия классов невелика и содержит всего шестнадцать элементов. Причем в этой иерархии только класс Open_polyline имеет несколько поколений наследников. Очевидно, что наиболее важным является общий базовый класс (Shape), несмотря на то, что он представляет абстрактное понятие о фигуре и никогда не используется для ее непосредственного воплощения.
14.3.1. Схема объекта
Как объекты размещаются в памяти? Как было показано в разделе 9.4.1, схема объекта определяется членами класса: данные-члены хранятся в памяти один за другим. Если используется наследование, то данные-члены производного класса просто добавляются после членов базового класса. Рассмотрим пример.
Класс Circle имеет данные-члены класса Shape (в конце концов, он является разновидностью класса Shape) и может быть использован вместо класса Shape. Кроме того, класс Circle имеет свой собственный член r, который размещается в памяти после унаследованных данных-членов.
Для того чтобы обработать вызов виртуальной функции, нам нужна еще одна порция данных в объекте класса Shape: информация о том, какая функция будет на самом деле вызываться при обращении к функции draw_lines() из класса Shape. Для этого обычно в таблицу функций заносится ее адрес. Эта таблица обычно называется vtbl (таблица виртуальных функций), а ее адрес часто имеет имя vptr (виртуальный указатель). Указатели обсуждаются в главах 17-18; здесь они действуют как ссылки. В конкретных реализациях языка таблица виртуальных функций и виртуальный показатель могут называться иначе. Добавив таблицу vptr и указатели vtbl к нашему рисунку, получим следующую диаграмму.
Поскольку функция draw_lines() — первая виртуальная функция, она занимает первую ячейку в таблице vtbl, за ней следует функция move(), вторая виртуальная функция. Класс может иметь сколько угодно виртуальных функций; его таблица vtbl может быть сколь угодно большой (по одной ячейке на каждую виртуальную функцию). Теперь, когда мы вызовем функцию x.draw_lines(), компилятор сгенерирует вызов функции, найденной в ячейке draw_lines() таблицы vtbl, соответствующей объекту x. В принципе код просто следует по стрелкам на диаграмме.
Итак, если объект x относится к классу Circle, будет вызвана функция Circle::draw_lines(). Если объект x относится к типу, скажем, Open_polyline, который использует таблицу vtbl точно в том виде, в каком ее определил класс Shape, то будет вызвана функция Shape::draw_lines(). Аналогично, поскольку в классе Circle не определена его собственная функция move(), при вызове x.move() будет выполнена функция Shape::move(), если объект x относится к классу Circle. В принципе код, сгенерированный для вызова виртуальной функции, может просто найти указатель vptr и использовать его для поиска соответствующей таблицы vtbl и вызова нужной функции оттуда. Для этого понадобятся два обращения к памяти и обычный вызов функции, — быстро и просто.
Класс Shape является абстрактным, поэтому мы не можем на самом деле непосредственно создать объект класса Shape, но класс Open_polyline имеет точно такую же простую структуру, поскольку не добавляет никаких данных-членов и не определяет виртуальную функцию. Таблица виртуальных функций vtbl определяется для каждого класса, в котором определена виртуальная функция, а не для каждого объекта, поэтому таблицы vtbl незначительно увеличивают размер программы.
Обратите внимание на то, что на рисунке мы не изобразили ни одной невиртуальной функции. В этом не было необходимости, поскольку об этих функциях мы не можем сказать что-то особенное и они не увеличивают размеры объектов своего класса. Определение функции, имеющей то же имя и те же типы аргументов, что и виртуальная функция из базового класса (например, Circle::draw_lines()), при котором функция из производного класса записывается в таблицу vtbl вместо соответствующей функции из базового класса, называется замещением (overriding). Например, функция Circle::draw_lines() замещает функцию Shape::draw_lines().
Почему мы говорим о таблицах vtbl и схемах размещения в

