Программирование >>  Дополнительные возможности наследования 

1 ... 96 97 98 [ 99 ] 100 101 102 ... 265


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:



1 ... 96 97 98 [ 99 ] 100 101 102 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика