|
Программирование >> Структурное программирование
Резюме С помощью виртуальных функций и полиморфизма становится возможным создавать и внедрять системы, которые являются легко расширяемыми. Программы могут быть написаны так, чтобы обрабатывать объекты типов, которых даже еще может быть нет, пока программа находится в стадии разработки. Виртуальные функции и полиморфное программирование могут устранить потребность в использовании логики оператора выбора switch. Программист может использовать возможности виртуальных функций для автоматического выполнения аналогичной логики, избегая таким образом разного рода ошибок, присущих логике оператора switch. Коды, принимающие решения относительно типов объектов и их представления, свидетельствуют о плохом стиле проектирования классов. Виртуальная функция объявляется с помощью ключевого слова virtual, предшествующего прототипу функции в базовом классе. Производные классы могут, если надо, иметь собственные реализации виртуальных функций базового класса, но если они их не имеют, то используются реализации, описанные в базовом классе. Когда виртуальная функция вызывается путем обращения к заданному объекту по имени и при этом используется операция доступа к элементу точка, тогда эта ссылка обрабатывается во время компиляции (это называется статическим связыванием) и в качестве вызываемой определяется функция класса данного объекта (или наследуемая этим классом). Имеются сл5аи, в которых полезно определять классы, для которых программист не намерен создавать какие-либо объекты. Такие классы называются абстрактными классами. Поскольку они применяются в качестве базовых классов в процессе наследования, мы обычно будем называть их абстрактными базовыми классами. Объекты абстрактного базового класса не могут быть реализованы. Классы, объекты которых могут быть реализованы, называются конкретными классами. Класс делается абстрактным путем объявления одной или более его виртуальных функций чисто виртуальными. Чистой виртуальной функцией является такая функция, у которой в ее объявлении тело определено как О (инициализатор равен 0). Если класс является производным от класса с чистой виртуальной функцией и если эта чистая виртуальная функция не определена в производном классе, то функция остается чистой виртуальной и в производном классе. Тогда производный класс также является абстрактным классом (и не может иметь каких-либо объектов). С-Н- включает такое свойство, как полиморфизм - возможность для объектов разных классов, связанных с помощью наследования, реагировать различным образом при обращении к одной и той же функции-элементу. Полиморфизм реализуется с помощью виртуальных функций. Глава 10 Если при использовании виртуальной функции запрос осуществляется с помощью указателя базового класса (или ссылки), то С++ выбирает правильную переопределенную функцию в соответствующем производном классе, связанном с данным объектом. Благодаря использованию виртуальных функций и полиморфизму, один и тот же вызов функции-элемента может привести к различным действиям в зависимости от типа объекта, принимающего этот вызов. Хотя мы не можем создавать объекты абстрактного базового класса, мы можем объявить указатели на абстрактный базовый класс. Эти указатели могут быть затем использованы, чтобы предоставить возможность для полиморфного оперирования объектами производных конкретных классов. В системы постоянно добавляются новые типы классов. Новые классы встраиваются при помощи динамического связывания, называемого также поздним связыванием. Во время компиляции нет необходимости знать тип объекта, чтобы скомпилировать вызов виртуальной функции. Во время выполнения программы вызов виртуальной функции будет соответствовать функции-элементу вызванного объекта. Динамическое связывание позволяет независимым дистрибьютерам программного обеспечения распространять свою продукцию, не выдавая фирменных секретов. Распространяемое программное обеспечение может состоять только из заголовочных и объектных файлов. Чтобы не раскрывать секреты программного обеспечения, не должно прикладываться никаких исходных текстов. Разработчики программного обеспечения могут использовать наследование для создания новых производных классов на основе тех классов, которые предоставлены им дистрибьютерами программного обеспечения. Программные средства, которые работают с классами, предоставленными дистрибьютерами, будут продолжать работать и с производными классами, используя (с помощью динамического связывания) переопределенные виртуальные функции, имеющиеся в этих классах. Динамическое связывание требует, чтобы во время выполнения программы вызов виртуальной функции-элемента был бы направлен варианту виртуальной функции соответствующего класса. Для этого служит таблица виртуальных методов, которая реализуется в виде массива, содержащего указатели на функции. У каждого класса, который содержит виртуальные функции, имеется таблица виртуальных методов. Для каждой виртуальной функции в классе таблица имеет элемент, содержащий указатель на вариант виртуальной функции, используемый в объектах данного класса. Виртуальная функция, используемая в некотором классе, может быть определена в этом классе или прямо или косвенно наследоваться из базового класса, стоящего выше в иерархии. Если базовый класс имеет виртуальную функцию-элемент, то производные классы могут переопределить эту функцию, но они могут этого и не делать. Таким образом, производный класс может использовать вариант виртуальной функции-элемента базового класса и это будет отражено в таблице виртуальных методов. Каждый объект класса, содержащего виртуальные функции, имеет указатель на таблицу виртуальных методов этого класса, недоступный для программиста. Во время выполнения программы вызовы виртуальных функций осуществляются через разыменование соответствующего указателя в таблице виртуальных методов. Просмотр таблицы виртуальных методов и операция разыменования указателя требуют минимальных затрат времени выполнения, обычно значительно меньших, чем самые лучшие коды клиентов. Если у класса имеются виртуальные функции, предусматривайте создание виртуального деструктора. Это приведет к тому, что все деструкторы производных классов станут виртуальными, даже если они имеют имена, отличные от имени деструктора базового класса. В этом случае, если объект в иерархии уничтожен явным использованием операции delete, примененной к указателю базового класса на объект производного класса, то будет вызван деструктор соответствующего класса. Терминология абстрактный базовый класс абстрактный класс виртуальная функция виртуальная функция базового класса виртуальный деструктор динамическое связывание иерархия классов исключение операторов switch ключевое слово virtual конструктор производного класса косвенный базовый класс логика оператора switch наследование неявное преобразование указателя переопределенная виртуальная функция повторное использование кодов позднее связывание полиморфизм преобразование указателя производного класса к указателю базового класса производный класс прямой базовый класс раннее связывание расширяемость ссылка на абстрактный класс ссылка на базовый класс ссылка на производный класс статическое связывание таблица виртуальных методов viable указатель на абстрактный класс указатель на базовый класс указатель на производный класс чистая виртуальная функция (=0) явное преобразование указателей Типичные ошибки программирования 10.1. Если в производном классе переопределяется виртуальная функция базового класса и данная функция не имеет тот же тип возвращаемого значения и ту же сигнатуру, что и соответствующая функция базового класса, то возникает синтаксическая ошибка. 10.2. Попытка создать объект абстрактного класса (т.е. класса, который содержит хотя бы одну чистую виртуальную функцию) является синтаксической ошибкой. 10.3. Объявление конструктора виртуальной функцией. Конструкторы не могут быть виртуальными.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |