|
Программирование >> Дополнительные возможности наследования
Mammal constructor... Mammal constructor... Dog constructor... Mammal sound! Woof! Dog destructor.,. Mammal destructor... Mammal destructor... В строке 34 в классе Dog происходит замещение метода базового класса SpeakO, в результате чего в случае вызова этой функции объектом класса Dog на экран выводится Woof!. В строке 42 создается объект blgAnimal класса Mammal, в результате чего вызывается конструктор класса Mammal и на экране появляется первая строка. В строке 43 создается объект Fido класса Dog, что сопровождается последовательным вызовом сначала конструктора класса Mammal, а затем конструктора класса Dog. Соответственно на экран выводится еще две строки. В строке 44 объект класса Mammal вызывает метод Speak(), а в строке 45 уже объект класса Dog обращается к этому методу. На экран при этом выводится разная информация, так как метод Speak() в классе Dog замещен. Наконец выполнение профаммы выходит за область видимости объектов и для их удаления вызываются соответствующие пары деструкторов. Перегрузка или замещение Эти схожие подходы приводят почти к одинаковым результатам. При перегрузке метода создается несколько вариантов этого метода с одним и тем же именем, но с разными сигнатурами. При замещении в производном классе используется метод с тем же именем и сигнатурой, что и в базовом классе, но с изменениями в теле функции. Спкрытпв мвтпда Оазовпгп класса в предыдущем примере при обращении к методу Speak() из объекта класса Dog профамма выполнялась не так, как было указано при объявлении метода SpeakO в базовом классе. Казалось бы, это то, что нам нужно. Если в классе Mammal есть некоторый метод MoveO, который замещается в классе Dog, то можно сказать, что метод Move О класса Dog скрывает метод с тем же именем в базовом классе. Однако в некоторых случаях результат может оказаться неожиданным. Усложним ситуацию. Предположим, что в классе Mammal метод Move() трижды перефужен. в одном варианте метод не требует параметров, в другом используется один целочисленный параметр (дистанция), а в третьем - два целочисленных параметра (скорость и дистанция). В классе Dog замещен метод Move() без параметров. Тем не менее попытка обратиться из объекта класса Dog к двум другим вариантам перефуженного метода класса Mammal окажется неудачной. Суть проблемы раскрывается в листинге 11.6. Листинг П.6. Сокрытие методов 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 Листинг 11.6. Сокрытие методов ffinclude <iostream.h> class Mammal { public: void Move() const { cout Mammal move one step\ n ; } void Move(int distance) const { cout Mammal move ; cout distance steps.\ n ; } protected: int itsAge; int itsWeight; class Dog : public Mammal { public; Возможно, последует сообщение, что функция скрыта! void MoveO const { cout << Dog move 5 steps.\ n ; } int mainO { Mammal bigAnimal; Dog fido; bigAnimal. MoveO; bigAnimal.Move(2); fido. MoveO; fido.Move(IO); return 0; } Mammal move one step Mammal move 2 steps. Dog move 5 steps. В данном примере из профаммы были удалены все другие методы и данные, рассмотренные нами ранее. В строках 8 и 9 в объявлении класса Mammal перефужаются методы Move(). В строке 23 происходит замещение метода MoveO без параметров в классе Dog. Данный метод вызывается для объектов разных классов в строках 30 и 32, и информация, выводимая на экран, подтверждает, что замещение метода проишо правильно. Однако строка 33 заблокирована, так как она вызовет ошибку компиляции. Хотя логично было предположить, что в классе Dog свободно можно использовать метод Move (int), поскольку замешен был только метод MoveO, но в действительности в данной ситуации, чтобы использовать Move (int), его также нужно заместить в классе Dog. В случае замешения одного из перефуженных методов скрытыми оказываются все варианты этого метода в базовом классе. Если вы хотите использовать в производном классе другие варианты перефуженного метода, то их также нужно заместить в этом классе. Часто случается ошибка, когда после попытки заместить метод в производном классе данный метод оказывается недоступным для класса из-за того, что профаммист забыл установить ключевое слово const, используемое при объявлении метода в базовом классе. Вспомните, что слово const является частью сигнатуры, а несоответствие сигнатур ведет к скрытию базового метода, а не к его замещению. Замвщвннв U сокрытие в следующем разделе главы будут рассматриваться виртуальные методы. Замещение виртуальных методов ведет к полиморфизму, а сокрытие методов разрушает полиморфизм. Скоро вы узнаете об этом больше. Вызов Оазивого мвтода Даже если вы заместили базовый метод, то все равно можете обратиться к нему, указав базовый класс, где хранится исходное объявление метода. Для этого в обращении к методу нужно явно указать имя базового класса, за которым следуют два символа двоеточия и имя метода. Например: Mammal: :Move(). Если в листинге 11.6 переписать строку 32 так, как показано ниже, то ошибка во время компиляции больше возникать не будет: 32: fido.Mammal::Move(): Такая запись, реализованная в листинге 11.7, называется явным обращением к методу базового класса. Листинг 11.7. Явиве оОращвнив к мвтвдд Овзввого хивсса 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Листинг 11.7, Явное обращение к методу базового класса Sinclude <iostream.h> class Mammal { public: void MoveO const { cout Mammal move one step\ n ; } void Move(int distance) const { cout << Mammal move << distance; cout steps.\ n ; protected:
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |