|
Программирование >> Дополнительные возможности наследования
Поскольку объекты с виртуальными методами должны поддерживать v-таблицу, то использование виртуальных функций всегда ведет к некоторому повышению затрат памяти и снижению быстродействия программы. Если вы работаете с небольшим классом, который не собираетесь делать базовым для других классов, то в этом случае нет никакого смысла использовать виртуальные методы. Объявляя виртуальньп! метод в программе, заплатить придется не только за v-таблицу (хотя добавление последующих записей потребует не так уж много места), но и за создание виртуального деструктора. Поэтому следует подумать, имеет ли смысл преобразовывать методы профаммы в виртуальные, а если да, то какие именно. Рвкомвнуувшся Используйте виртуальные методы только в том случае, если программа содержит базовый и производные классы. Используйте виртуальный деструктор, если в программе были созданы виртуальные методы. Нв рвкомвнудвшся Не пытайтесь создать виртуальный конструктор. Резюме Сегодня вы узнали, как наследовать новые классы от базового класса. В этой главе рассматривалось наследование с ключевым словом public и использование виртуальных функций. Во время наследования в производнь;е классы передаются все открь;-тые и защищенные данные и функции из базового класса. Защищенные данные базового класса открыты для всех производных классов, но закрыты для всех других классов профаммы. Но даже производные классы не могут получить доступ к закрытым данным и функциям базового класса. Конструкторы могут инициализироваться до выполнения тела конструктора. При этом вызывается конструктор базового класса, и туда могут быть переданы данные в виде параметров. Функции, объявленные в базовом классе, могут быть замещены в производных классах. Если при этом функция объявлена как виртуальная, а обращение к функции от объекта осуществляется с помощью указателя на объект или ссылки, то вызываться будет тот замещенный вариант функции, который соответствует типу текущего объекта. Методы базового класса можно вызывать явным обращением, когда в строке вызова сначала указывается имя базового класса с двумя символами двоеточия после него. Например, если класс Dog произведен от класса Mammal, то к методу базового класса напрямую можно обратиться следующим выражением: Mammal: :walk(). Если в классе используются виртуальные методы, то следует объявить также и виртуальный десфуктор. Он необходим для того, чтобы быть уверенным в удалении части объекта, относящейся к производному классу, если удаление объекта осуществлялось с помощью указателя базового класса. Нельзя создать виртуальный консфуктор. В то же время можно создать виртуальный конструктор-копировщик и эффективно его использовать с помощью виртуальной функции, вызывающей консфуктор-копировщик. �2722112 Вопросы u ответы Наследуются ли данные и функции-члены базового класса в последующие поколения производных классов? Скажем, если класс Dog произведен от класса Mammal, а класс Mammal произведен от класса Animals, унаследует ли класс Dog данные и функции класса Animals? Да. Если последовательно производить ряд классов, последний класс в этом ряду унаследует всю сумму данных и методов предыдущих базовых классов. Если в предьщущем примере в классе Mammal будет замещена функция, описанная в классе Animals, то какой вариант функции получит класс Dog? Если класс Dog наследуется от класса Mammal, то он получит функцию в том виде, в каком она существует в классе Mammal, т.е. замещенную. Можно ли в производном классе описать как private функцию, которая перед этим была описана в базовом классе как public? Можно. Функция может быть не только защищена в производном классе, но и закрыта. Она останется закрытой для всех последующих классов, произведенных от этого. В каких случаях не следует делать фуншщи класса виртуальными? Описание первой виртуальной функции вызовет создание v-таблицы, что потребует времени и дополнительной памяти. Последующее добавление виртуальных функций будет тривиальным. Многие профаммисты увлекаются созданием виртуальных функций и полагают, что если в программе есть уже одна виртуальная функция, то и все другие должны быть виртуальными. В действительности это не так. Создание виртуальных функций всегда должно отвечать решению конкретных задач. Предположим, что некоторая функция без параметров была описана в базовом классе как виртуальная, а затем перефужена таким образом, чтобы принимать один и два целочисленных параметра. Затем в производном классе был замещен вариант функции с одним целочисленным параметром. Что произойдет, если с помощью указателя, связанного с объектом производного класса, вызвать вариант функции с двумя параметрами? Замещение в производном классе варианта функции с одним параметром скроет от объектов этого класса все остальные варианты функции. Поэтому в случае обращения, описанного в вопросе, компилятор покажет сообщение об ошибке. КОААОКВиуМ в этом разделе предлагаются вопросы для самоконтроля и укрепления полученных знаний и приводится несколько упражнений, которые помогут закрепить ваши практические навыки. Попытайтесь самостоятельно ответить на вопросы теста и выполнить задания, а потом сверьте полученные результаты с ответами в приложении Г. Не приступайте к изучению материала следующей главы, если для вас остались неясными хотя бы некоторые из предложенных ниже вопросов. Тест 1. Что такое v-таблица? 2. Что представляет собой виртуальный деструктор? 3. Можно ли объявить виртуальный конструктор? 4. Как создать виртуальный конструктор-копировщик? 5. Как вызвать функцию базового класса из объекта производного класса, если в производном классе эта функция была замещена? 6. Как вызвать функцию базового класса из объекта производного класса, если в производном классе эта функция не была замещена? 7. Если в базовом классе функция объявлена как виртуальная, а в производном классе виртуальность функции указана не была, сохранится ли функция как виртуальная в следующем произведенном классе? 8. С какой целью используется ключевое слово protected? Упражнения 1. Объявите виртуальную функцию, которая принимает одно целочисленное значение и возвращает void. 2. Запищите объявление класса Square, произведенного от класса Rectangle, который, в свою очередь, произведен от класса Shape. 3. Предположим, что в предьщущем примере объект класса Shape не использует параметры, объект класса Rectangle принимает два параметра (length и width), а объект класса Square - один параметр (length); запищите конструктор для класса Square. 4. Запищите виртуальный конструктор-копировщик для класса Square, взятого из упражнения 3. 5. Жучки: что неправильно в следующем программном коде? void SomeFunctlon(Shape); Shape * pRect = new Rectangle; SomeFunctlon(*pRect); 6. Жучки: что неправильно в следующем программном коде? class ShapeO { public; ShapeO; virtual -ShapeO; virtual Shape(const Shape&);
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |