- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Освой самостоятельно за 21 день - Джесс Либерти
Шрифт:
Интервал:
Закладка:
15: void Sleep()const { cout << "shhh. I'm sleeping.n"; }
16:
17:
18: protected:
19: int itsAge;
20: int itsWeight;
21: };
22:
23: class Dog : public Mammal
24: {
25: public:
26:
27: // Конструкторы
28: Dog(){ cout << "Dog constructor...n"; }
29: ~Dog(){ cout << "Dog destructor...n"; }
30:
31: // Другие методы
32: void WagTail() const { cout << "Tail wagging...n"; }
33: void BegForFood() const { cout << "Begging for food...n"; }
34: void Speak() const { cout << "Woof!n"; }
35:
36: private:
37: BREED itsBreed;
38: };
39:
40: int main()
41: {
42: Mammal bigAnimal;
43: Dog fido;
44: bigAnimal.Speak();
45: fido.Speak();
46: return 0;
47: }
Результат:
Mammal constructor...
Mammal constructor...
Dog constructor...
Mammal sound!
Woof!
Dog destructor...
Mammal destructor...
Mammal destructor...
Анализ: В строке 34 в классе Dog происходит замещение метода базового класса
Speak(), в результате чего в случае вызова этой функции объектом класса Dog на экран выводится Woof!. В строке 42 создается объект bigAnimal класса Mammal, в результате чего вызывается конструктор класса Mammal и на экране появляется первая строка. В строке 43 создается объект Fido класса Dog, что сопровождается последовательным вызовом сначала конструктора класса Mammal, а затем конструктора класса Dog. Соответственно на экран выводится еще две строки.
В строке 44 объект класса Mammal вызывает метод Speak(), а в строке 45 уже объект класса Dog обращается к этому методу. На экран при этом выводится разная информация, так как метод Speak() в классе Dog замещен. Наконец выполнение программы выходит за область видимости объектов и для их удаления вызываются соответствующие пары деструкторов.
Перегрузка или замещение
Эти схожиеподходы приводят почти к одинаковым результатам. При перегрузке метода создается несколько вариантов этогометода с одним и тем же именем, но с разными сигнатурами. При замещении в производном классе используется метод с тем же именем и сигнатурой, что и в базовом классе, но с изменениями в теле функции.
Сокрытие метода базового класса
В предыдущем примере при обращении к методу Speak() из объекта класса Dog программа выполнялась не так, как было указано при объявлении метода Speak() в базовом классе. Казалось бы, это то, что нам нужно. Если в классе Mammal есть некоторый метод Move(), который замещается в классе Dog, то можно сказать, что метод Move() класса Dog скрывает метод с тем же именем в базовом классе. Однако в некоторых случаях результат может оказаться неожиданным.
Усложним ситуацию. Предположим, что в классе Mammal метод Move() трижды перегружен. В одном варианте метод не требует параметров, в другом используется один целочисленный параметр (дистанция), а в третьем — два целочисленных параметра (скорость и дистанция). В классе Dog замещен метод Move() без параметров. Тем не менее попытка обратиться из объекта класса Dog к двум другим вариантам перегруженного метода класса Mammal окажется неудачной. Суть проблемы раскрывается в листинге 11.6.
Листинг 11.6. Сокрытие методов
1: //Листинг 11.6. Сокрытие методов
2:
3: #include <iostream.h>
4:
5: class Mammal
6: {
7: public:
8: void Move() const { cout << "Mammal move one stepn"; }
9: void Move(int distance) const
10: {
11: cout << "Mammal move ";
12: cout << distance <<" steps.n";
13: }
14: protected:
15: int itsAge;
16: int itsWeight;
17: };
18:
19: class Dog : public Mammal
20: {
21: public:
22: // Возможно, последует сообщение, что функция скрыта!
23: void Move() const { cout << "Dog move 5 steps.n"; }
24: };
25:
26: int main()
27: {
28: Mammal bigAnimal;
29: Dog fido;
30: bigAnimal.Move();
31: bigAnimal.Move(2);
32: fido.Move();
33: // fido.Move(10);
34: return 0;
35: }
Результат:
Mammal move one step
Mammal move 2 steps.
Dog move 5 steps.
Анализ: В данном примере из программы были удалены все другие методы и данные, рассмотренные нами ранее. В строках 8 и 9 в объявлении класса Mammal перегружаются методы Move(). В строке 23 происходит замещение метода Move() без параметров в классе Dog. Данный метод вызывается для объектов разных классов в строках 30 и 32, и информация, выводимая на экран, подтверждает, что замещение метода прошло правильно.
Однако строка 33 заблокирована, так как она вызовет ошибку компиляции. Хотя логично было предположить, что в классе Dog свободно можно использовать метод Move(int), поскольку замещен был только метод Move(), но в действительности в данной ситуации, чтобы использовать Move(int), его также нужно заместить в классе Dog. В случае замещения одного из перегруженных методов скрытыми оказываются все варианты этого метода в базовом классе. Если вы хотите использовать в производном классе другие варианты перегруженного метода, то их также нужно заместить в этом классе.
Часто случается ошибка, когда после попытки заместить метод в производном классе данный метод оказывается недоступным для класса из-за того, что программист забыл установить ключевое слово const, используемое при объявлении метода в базовом классе. Вспомните, что слово const является частью сигнатуры, а несоответствие сигнатур ведет к скрытию базового метода, а не к его замещению.
Замещение и сокрытие
В следующем разделе главы будут рассматриваться виртуальные методы. Замещение виртуальных методов ведет к полиморфизму, а сокрытие методов разрушает поли- морфизм. Скоро вы узнаете об этом больше.
Вызов базового метода
Даже если вы заместили базовый метод, то все равно можете обратиться к нему, указав базовый класс, где хранится исходное объявление метода. Для этого в обращении к методу нужно явно указать имя базового класса, за которым следуют два символа двоеточия и имя метода. Например: Mammal: :Move().
Если в листинге 11.6 переписать строку 32 так, как показано ниже, то ошибка во время компиляции больше возникать не будет:
32: fido.Mammal::Move();
Такая запись, реализованная в листинге 11.7, называется явным обрашением к методу базового класса.
Листинг 11.7. Явное обращение к методу базового класса
1: //Листинг 11.7. Явное обращение к методу базового класса
2:
3: #include <iostream.h>
4:
5: class Mammal
6: {
7: public:
8: void Move() const { cout << "Mammal move one stepn"; }
9: void Move(int distance) const
10: {
11: cout << "Mammal move " << distance;
12: cout << " steps.n";
13: }
14:
15: protected:
16: int itsAge;
17: int itsWeight;
18: };
19:
20: class Dog : public Mammal
21: {
22: public:
23: void Move()const;
24:
25: };
26:
27: void Dog::Move() const
28: {
29: cout << "In dog move...n";
30: Mammal::Move(3);
31: }
32:
33: int main()
34: {
35: Mammal bigAnimal;
36: Dog fido;
37: bigAnimal.Move(2);
38: fido.Mammal::Move(6);
39: return 0;
40: }
Результат:
Mammal move 2 steps.
Mammal move 6 steps.
Анализ: В строке 35 создается объект bigAnimal класса Mammal, а в строке 36 — объект fido класса Dog. В строке 37 вызывается метод Move(int) из базового класса для объекта класса Dog.
В предыдущей версии программы мы столкнулись с проблемой из-за того, что в классе Dog доступен только один замещенный метод Move(), в котором не задаются параметры. Проблема была разрешена явным обращением к методу Move(int) базового класса в строке 38.
Рекомендуется:Повышайте функциональные возможности класса путем создания новых производных классов. Изменяйте выполнение отдельных функций в производных классах с помощью замещения методов.
Не рекомендуется:Не допускайте сокрытие функций базового класса из-за несоответствия сигнатур.
Виртуальные методы
В этой главе неоднократно подчеркивалось, что объекты класса Dog одновременно являются объектами класса Mammal. До сих пор под этим подразумевалось, что объекты класса Dog наследуют все атрибуты (данные) и возможности (методы) базового класса. Но в языке C++ принципы иерархического построения классов несут в себе еще более глубинный смысл.
Полиморфизм в C++ развит настолько, что допускается присвоение указателям на базовый класс адресов объектов производных классов, как в следующем примере:
Mammal* pMammal = new Dog;
Данное выражение создает в области динамической памяти новый объект класса Dog и возвращает указатель на этот объект, который является указателем класса Mammal. Это вполне логично, так как собака — представитель млекопитающих.