Чтение онлайн

на главную - закладки

Жанры

Освой самостоятельно С++ за 21 день.

Либерти Джесс

Шрифт:

Листинг 13.1. Умеют ли лошади летать...

1: // Листинг 13.1. Умеют ли лошади летать...

2: // Фильтрация метода Fly в классе Horse

3:

4: #include <iostream.h>

5:

6: class Horse

7: {

8: public:

9: void Gallop{ cout << "Galloping...\n"; }

10: virtual void Fly { cout << "Horses can't fly.\n"; }

11: private:

12: int itsAge;

13: };

14:

15: class Pegasus : public Horse

16: {

17: public:

18: virtual void Fly { cout << "I can fly! I can fly! I can fly!\n"; }

19: };

20:

21: const int NumberHorses = 5;

22: int main

23: {

24: Horse* Ranch[NumberHorses];

25: Horse* pHorse;

26: int choice,i;

27: for (i=0; i<NumberHorses; i++)

28: {

29: cout << "(1)Horse (2)Pegasus: ";

30: cin >> choice;

31: if (choice == 2)

32: pHorse = new Pegasus;

33: else

34: pHorse = new Horse;

35: Ranch[i] = pHorse;

36: }

37: cout << "\n";

38: for (i=0; i<NumberHorses; i++)

39: {

40: Ranch[i]->Fly;

41: delete Ranch[i];

42: }

43: return 0;

44: }

Результат:

(1)Horse (2)Pegasus; 1

(1)Horse (2)Pegasus: 2

(1)Horse (2)Pegasus: 1

(1)Horse (2)Pegasus: 2

(1)Horse (2)Pegasus: 1

Horses can't fly.

I can fly! I can fly! I can fly!

Horses can't fly.

I can fly! I can fly! I can fly!

Horses can't fly.

Анализ:

Безусловно, эта программа будет работать ценой добавления в класс Horse редко используемого метода Fly. Это произошло в строке 10. Для объектов данного класса этот метод констатирует факт, что лошади летать не умеют. И только для объекта Pegasus метод замещается в строке 18 таким образом, что при вызове его объект заявляет, что умеет летать.

В строке 24 используется массив указателей на объекты класса Horse, с помощью которого метод Fly вызывается для разных объектов класса. В зависимости от того, для какого из объектов в данный момент вызывается метод, программа выводит на экран разные сообщения.

Примечание:Показанный выше пример программы был значительно сокращен, чтобы выделить именно те моменты, которые сейчас рассматриваются. Так, для простоты программы из нее были удалены конструктор и виртуальные деструкторы.

Перенос метода вверх по иерархии классов

Очень часто для решения подобных проблем объявление метода переносят вверх по иерархическому списку классов, чтобы сделать его доступным большему числу производных классов. Но при этом есть угроза, что базовый класс уподобится кладовке, захламленной старыми вещами. Такой подход делает программу громоздкой и нарушает саму идею иерархии классов

в C++, когда производные классы дополняют своими функциями небольшой набор общих функций базового класса.

Противоречие состоит в том, что при переносе функции из производных классов вверх по иерархии в базовый класс трудно сохранить уникальность интерфейсов производных классов. Так, можно предположить, что у наших двух классов Bird и Horse есть базовый класс Animal, в котором собраны функции, общие для всех производных классов, например функция питания — Eat. Перенеся метод Fly в базовый класс, придется позаботиться о том, чтобы этот метод вызывался только в некоторых производных классах.

Приведение указателя к типу производного класса

Продолжая держаться за одиночное наследование, эту проблему можно решить таким образом, что метод Fly будет вызываться только в случае, если указатель в данный момент связан с объектом Pegasus. Для этого необходимо иметь возможность обратиться к указателю и определить, на какой объект он указывает в текущий момент. Такой подход известен как RTTI (Runtime Type Identification — определение типа при выполнении). Но возможность выполнения RTTI была добавлена только в последние версии компиляторов C++.

Если ваш компилятор не поддерживает RTTI, можете реализовать его собственными силами, добавив в программу метод, который возвращает перечисление типов каждого класса. Возвращенное значение можно анализировать во время выполнения программы и допускать вызов метода Fly только в том случае, если возвращается значение Pegasus.

Примечание:Не злоупотребляйте использованием RTTI в своих программах, так как этот подход рассматривается как аварийный и свидетельствует о том, что структура программы изначально была плохо продумана. Профессиональный программист предпочтет использование виртуальных функций, шаблонов или множественного наследования, речь о котором пойдет ниже в этой главе.

Чтобы вызвать метод Fly, необходимо во время выполнения изменить тип указателя, определив, что он связан не с объектом Horse, а с объектом производного класса Pegasus. Этот способ называют приведением вниз, поскольку объект базового класса Horse приводится к объекту производного класса Pegasus.

Этот подход, хоть и с неохотой, теперь уже официально признан в C++, и для его реализации добавлен новый оператор — dynamic_cast.

Если в программе создан указатель на объекты базового класса Horse и ему присвоен адрес объекта производного класса Pegasus, то такой указатель можно использовать полиморфно. Чтобы обратиться к методу производного класса, нужно динамически подменить указатель базового класса указателем производного класса с помощью оператора dynamic_cast.

Поделиться:
Популярные книги

Наследник 2

Шимохин Дмитрий
2. Старицкий
Фантастика:
попаданцы
альтернативная история
фэнтези
5.75
рейтинг книги
Наследник 2

Неудержимый. Книга XVIII

Боярский Андрей
18. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XVIII

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита

Взводный

Берг Александр Анатольевич
5. Антиблицкриг
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Взводный

Пять попыток вспомнить правду

Муратова Ульяна
2. Проклятые луной
Фантастика:
фэнтези
эпическая фантастика
5.00
рейтинг книги
Пять попыток вспомнить правду

Девочка для Генерала. Книга первая

Кистяева Марина
1. Любовь сильных мира сего
Любовные романы:
остросюжетные любовные романы
эро литература
4.67
рейтинг книги
Девочка для Генерала. Книга первая

Неудержимый. Книга XI

Боярский Андрей
11. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XI

Сумеречный Стрелок 4

Карелин Сергей Витальевич
4. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 4

Черный маг императора 3

Герда Александр
3. Черный маг императора
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора 3

Матабар

Клеванский Кирилл Сергеевич
1. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар

Мастер 6

Чащин Валерий
6. Мастер
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 6

АН (цикл 11 книг)

Тарс Элиан
Аномальный наследник
Фантастика:
фэнтези
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
АН (цикл 11 книг)

На границе империй. Том 7. Часть 4

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
На границе империй. Том 7. Часть 4

Прорвемся, опера! Книга 2

Киров Никита
2. Опер
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прорвемся, опера! Книга 2