- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
• Если базовый класс для класса D является открытым, то имена его открытых членов могут использоваться любыми функциями.
Эти определения игнорируют понятие дружественной функции или класса и другие детали, которые выходят за рамки рассмотрения нашей книги. Если хотите стать крючкотвором, читайте книги Stroustrup, The Design and Evolution of C++ (Страуструп, “Дизайн и эволюция языка С++”), The C++ Programming Language (Страуструп, “Язык программирования С++”) и стандарт 2003 ISO C++. Мы не рекомендуем вам становиться крючкотвором (т.е. вникать в мельчайшие детали языковых определений) — быть программистом (разработчиком программного обеспечения, инженером, пользователем, назовите как хотите) намного увлекательнее и полезнее для общества.
14.3.5. Чисто виртуальные функции
Абстрактный класс — это класс, который можно использовать только в качестве базового. Абстрактные классы используются для представления абстрактных понятий; иначе говоря, мы используем абстрактные классы для описания понятий, которые являются обобщением общих характеристик связанных между собой сущностей. Описанию абстрактного понятия (abstract concept), абстракции (abstraction) и обобщению (generalization) посвящены толстенные книги по философии. Однако философское определение абстрактного понятия мало полезно. Примерами являются понятие “животное” (в противоположность конкретному виду животного), “драйвер устройства” (в противоположность драйверу конкретного вида устройств) и “публикация” (в противоположность конкретному виду книг или журналов). В программах абстрактные классы обычно определяют интерфейсы групп связанных между собой классов (иерархии классов).
В разделе 14.2.1 мы видели, как создать абстрактный класс, объявив его конструктор в разделе protected. Существует другой — более распространенный — способ создания абстрактного класса: указать, что одна или несколько его виртуальных функций будет замещена в производном классе. Рассмотрим пример.
class B { // абстрактный базовый класс
public:
virtual void f()=0; // чисто виртуальная функция
virtual void g()=0;
};
B b; // ошибка: класс B — абстрактный
Интересное обозначение =0 указывает на то, что виртуальные функции B::f() и B::g() являются чистыми, т.е. они должны быть замещены в каком-то производном классе. Поскольку класс B содержит чисто виртуальную функцию, мы не можем создать объект этого класса. Замещение чисто виртуальных функций устраняет эту проблему.
class D1:public B {
public:
void f();
void g();
};
D1 d1; // OK
Несмотря на то что все чисто виртуальные функции замещаются, результирующий класс остается абстрактным.
class D2:public B {
public:
void f();
// no g()
};
D2 d2; // ошибка: класс D2 — (по-прежнему) абстрактный
class D3:public D2 {
public:
void g();
};
D3 d3; // OK
Классы с чисто виртуальными функциями обычно описывают исключительно интерфейс; иначе говоря, они, как правило, не содержат данных-членов (эти данные хранятся в производных классах) и, следовательно, не имеют конструкторов (если инициализация данных-членов не нужна, то необходимость в конструкторах отпадает).
14.4. Преимущества объектно-ориентированного программирования
Когда мы говорим, что класс Circle является производным от класса Shape, или разновидностью класса Shape, то делаем это для того, чтобы достичь следующих целей (по отдельности или всех вместе).
• Наследование интерфейса. Функция, ожидающая аргумент класса Shape (обычно в качестве аргумента, передаваемого по ссылке), может принять аргумент класса Circle (и использовать его с помощью интерфейса класса Shape).
• Наследование реализации. Когда мы определяем класс Circle и его функции-члены, мы можем использовать возможности (т.е. данные и функции-члены), предоставляемые классом Shape.
Проект, в котором не используется наследование интерфейса (т.е. проект, в котором объект производного класса нельзя использовать вместо объекта открытого базового класса), следует признать плохим и уязвимым для ошибок. Например, мы могли бы определить класс Never_do_this, относительно которого класс Shape является открытым базовым классом. Затем мы могли бы заместить функцию Shape::draw_lines() функцией, которая не рисует фигуру, а просто перемещает ее центр на 100 пикселей влево. Этот проект фатально неверен, поскольку, несмотря на то, что класс Never_do_this может предоставить интерфейс класса Shape, его реализация не поддерживает семантику (т.е. поведение), требуемое классом Shape. Никогда так не делайте!
Преимущества наследования интерфейса проявляются в использовании интерфейса базового класса (в данном случае класса Shape) без информации о реализациях (в данном случае классах, производных от класса Shape).
Преимущества наследования интерфейса проявляются в упрощении реализации производных классов (например, класса Circle), которое обеспечивается возможностями базового класса (например, класса Shape).
Обратите внимание на то, что наш графический проект сильно зависит от наследования интерфейса: “графический движок” вызывает функцию Shape::draw(), которая в свою очередь вызывает виртуальную функцию draw_lines() класса Shape, чтобы она выполнила реальную работу, связанную с выводом изображений на экран. Ни “графический движок”, ни класс Shape не знают, какие виды фигур существуют. В частности, наш “графический движок” (библиотека FLTK и графические средства операционной системы) написан и скомпилирован за много лет до создания наших графических классов! Мы просто определяем конкретные фигуры и вызываем функцию attach(), чтобы связать их с объектами класса Window в качестве объектов класса Shape (функция Window::attach() получает аргумент типа Shape&; см. раздел Г.3). Более того, поскольку класс Shape не знает о наших графических классах, нам не нужно перекомпилировать класс Shape каждый раз, когда мы хотим определить новый класс графического интерфейса.
Иначе говоря, мы можем добавлять новые фигуры, не модифицируя существующий код. Это “святой Грааль” для проектирования, разработки и сопровождения программного обеспечения: расширение системы без ее модификации. Разумеется, существуют пределы, до которых мы можем расширять систему, не модифицируя существующие классы (например, класс Shape предусматривает довольно ограниченный набор операций), и этот метод не может решить все проблемы программирования (например, в главах 17–19 определяется класс vector; наследование здесь мало может помочь). Однако наследование интерфейса — один из мощных методов проектирования и реализации систем, устойчивых к изменениям.
Аналогично наследование реализации позволяет сделать многое, но тоже не является панацеей. Помещая полезные