Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 76
Текст из файла (страница 76)
('2.5) Реализуйте простой механизм регулярных выражений для поиска в строках типа 5)геля. ('1.5) Модифицируйте механизм поиска из В11.14[1Ц для работы со стандартным классом лгг(ля. Заметьте, что вы не можете модифицировать класс вгг(ля. (*2) Напишите программу, которая совершенно нечитабельна из-за применения макросов и определения пользовательских операций. Идея: определите операцию» так, чтобы она означала — (и наоборот) для 1й/Т, а затем макросом определите 1))/Т как 1лг. Переопределите популярные функции, чтобы они принимали ссылочные аргументы.
Ряд запутываюших комментариев окончательно «украсят» ваше произведение. (*3) Передайте результат В11.14[13[ вашему другу. Посмотрите за тем, как ваш друг будет разбираться со смыслом программы. В конце концов, вы поймете, чего вам следует избегать. (*2) Определите тип Рес4 как вектор из четырех элементов типа/?оаг. Определите операцию [) для Рес4. Определите операции», —, *, /, =, »=, -=, *= и /= для комбинации операндов типа Рес4 и типа/2оаг. (*3) Определите класс Маг4 как вектор четырех элементов типа Рес4. Определите операцию [ ) для типа Маг4 так, чтобы она возврашала Рес4. Определите обычные матричные операции для Маг4.
Определите функцию, реализуюшую метод исключений Гаусса. ('2) Определите класс Ресгог, аналогичный Рес4, но с размером, задаваемым конструктором Ресгог:: )лесгог ((лг) . (*3) Определите класс Малтх, аналогичный Маг4, но с размерами, задаваемыми конструктором Магг(х:: Мали((лб глг) .
370 Глава 11. Перегрузка операций 19. (*2) Завершите класс Рте го Т из я11.11 и протестируйте его. По крайней мере определите для этого класса операции *, ->, =, з-з- и —. Сделайте так, чтобы ошибка времени выполнения возникала только при попытке разыменования недействительных ссылок. 20. (*1) При наличии определений хггит Я 1(пгх, у; 1; мгит Т (еоаг* р; соаг* о; 1; дайте определение класса С, позволяюшего использовать х и р нз Ю и Тпримерно так же, как если бы они были членами С. 21.
(*1.5) Определите класс Ьи1ех для хранения индекса функции возведения в степень туром (Ыоиоге, 1адех) . Найдите возможность для 2**1отрабатывать в виде вызова туров (2, 1) . 22. (*2) Определите класс 1таяуааеу для представления мнимых чисел. Определите класс Сотр1ех на базе класса 1тая)вагу.
Реализуйте основные арифметические операции. Наследование классов Не множьте объекты без необходимости. — В. Оккам Концепции и классы — производные классы — функции-члены — конструирование и уничтожение — иерархии классов — поля типа — виртуальные функции — абстрактные классы — традиционные иерархии классов — абстрактные классы как интерфейсы — локализация создания объекта — абстрактные классы и иерархии классов — советы — упражнения. 12.1. Введение Из языка Япш!а язык С++ позаимствовал концепцию класса как пользовательского типа и концепцию классовых иерархий. Дополнительно он заимствовал фундаментальную идею о том, что классы моделируют концепции из мира программ и из реального мира.
Язык С++ содержит конструкции, которые непосредственно поддерживают концепции проектирования. Применение таких языковых конструкций с целью прямого воплощения дизайнерских идей свидетельствует об эффективном использовании С++. В то же время, если эти конструкции используются в качестве необязательных подпорок для традиционных стилей программирования, то это не самый эффективный способ программирования на С++. Никакие концепции не существует в абсолютной изоляции.
Они сосуществуют и взаимодействуют друг с другом, и в этом проявляется вся их мощь. Попробуем выяснить, что такое автомобиль. Скоро у нас появятся понятия колес, двигателей, водителей, пешеходов, грузовиков, скорой помощи, дорог, масла, мотелей и т.д. Поскольку мы хотим использовать классы для представления концепций, то мы неизбежно сталкиваемся с вопросом о том, как можно программным способом отразить связи между концепциями? Ясно, что мы не можем непосредственно в языке отразить какие угодно абстрактные связи. Если бы даже могли, то вряд ли бы захотели это делать. Наши классы должны быть уже реальных концепций и должны быть более точно определены.
Понятие производного класса и реализующий его ЗУ2 Глава 12. Наследование классов языковый механизм наследования классов призваны выразить понятие общности типов. Например, понятия круга и треугольника имеют общее в том отношении, что оба онн суть фигуры; это значит, что понятие фигуры является общим для ннх понятием.
Таким образом, нам нужно явным образом указать, что то общее, что есть у классов Сйс(е (круг) и Тнащ!е (треугольник), сосредоточено в классе оваре (фигура). Если же мы будем манипулировать лишь кругами и треугольниками без привлечения более общего понятия формы, то мы упустим что-то весьма существенное. В данной главе подробно изучаются смысл и значение этой простой идеи, лежащей в основе так называемого обьектно-ориентированного программирования.
Соответствующие средства языка и приемы программирования изучаются постепенно в направлении от простого и конкретного к более изощренному н абстрактному. Для многих программистов это будет движение от хорошо знакомого к существенно менее известному. Это нельзя назвать движением от «старых плохих приемов программирования» к «единственно правильному стилю». Когда я указываю на ограничения одного метода в качестве мотивации для перехода к другому, я всегда это делаю в контексте некоторой задачи; для другой задачи и в ином контексте первый метод может снова стать наилучшим.
Множество полезных программ было написано с применением всех рассматриваемых здесь приемов и методов. Главная цель состоит в том, чтобы помочь вам понять самую суть этих методов, дабы вы могли осознанно и со знанием дела осуществлять их выбор в контексте реальных задач. Сначала я рассматриваю основные средства языка, поддерживающие объектно-ориентированное программирование. Затем эти средства будут использованы для хорошо структурированной разработки довольно большого практического примера. Иные средства поддержки объектно-ориентированного программирования, такие как множественное наследование и динамическая идентификация типов на этапе выполнения (гцп-йпе гуре Ыеп11Т1саг(оп), рассматриваются в главе 15. 12.2.
Производные классы Рассмотрим программу для обработки информации о сотрудниках (ешр1оуеев) некоторой фирмы. Такая программа может содержать следующую структуру данных по сотрудникам фирмы: ввтсг Етр!оуве ввдпдЯт пате, ТатФу пате; слог т(ФФ!е иипа1; Васе Вге(пд Фаге; вьот Ферагиавт; У... )' Теперь попытаемся определить структуру данных для менеджеров компании: тгисг Мапааес 1 Етр!оуее етр; У общие сведении о менедже (кок о сотруднике вообще) ) 2 2 Производные классы 373 Ьвг<Етргоуее*> дгоир; й подчиненные ллогг 1вге1; У... )' Менеджеры также являются сотрудниками; соответствующие данные хранятся в поле етр класса Мапаяег.
Для читателя программы это может быть вполне ясно, но компилятору и иным программным средствам ничто не говорит о том, что Мапалег является в то же самое время и Етр!оуее. Указатель Мапааег* имеет тип, отличный от указателя Етр1оуее*, так что нельзя просто так использовать один из них там, где требуется другой. В частности, нельзя поместить объект типа Мапаяег в список объектов типа Етр1оуее, не написав для этого специальный код.
Можно, например, применить явное преобразование типа к Мапаяег*, либо поместить в указанный список адрес члена етр. Оба этих решения неэлегантны и могут запутать суть дела. Правильный подход — явно высказать утверждение, что Мапааег есть в то же время и Етр!оуее: глгисг Мапааег: риЬЫс Етр!оуее ) вег<Етр!оуее* > Люир; влогг 1еге1; й... )' Здесь класс Мападег указан как производный (йегйгей) от класса Етр1оуее, который, в свою очередь, является, тем самым, базовым классом (Ьаве с(овв) для класса Мапалег. В результате этого определения класс Мапаяег имеет все члены класс етр1оуее (гзгвг пате, аераптепг и т.д.) в дополнение к своим собственным членам (ягоир, 1еге1 и т.д.).
Рассмотренный только что механизм наследования классов (с!оввез тлеьдгопсе) графически отображается с помощью стрелки, направленной от производного класса к базовому, и показывающей, что именно производный класс ссылается но базовый (а не наоборот): Етргоуее Мападег Часто говорят, что производный класс наследует свойства базового, и именно поэтому такая связь классов называется наследованием.
Иногда базовый класс называют суперклассом (зирегс!авв), а производный класс — подклассом (виЬс!авв). Эта терминология часто смущает людей, которые понимают, что данные в объектах производного класса являются надмножеством данных объектов базового класса. Производный класс шире своего базового класса в том смысле, что он содержит больше данных и функций. Популярная трактовка механизма наследования представляет объект производного класса как объект базового класса с дополнительной информацией, специфичной лишь для производного класса, добавленной в конец.