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

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

Жанры

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

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

Шрифт:

Примечание:Во время компиляции неизвестно, объект какого класса захочет создать пользователь и какой именно вариант метода Speak будет использоваться. Указатель ptr связывается со своим объектом только во время выполнения программы. Такое связывание указателя с объектом называется динамическим, в отличие от статического связывания, происходящего во время компиляции программы.

Как работают виртуальные методы

 При

создании объекта в производном классе, например в классе Dog, сначала вызывается конструктор базового, а затем — производного класса. Схематично объект класса Dog показан на рис. 11.2. Обратите внимание, что объект производного класса состоит как бы из двух частей, одна из которых создается конструктором базового класса, а другая — конструктором производного класса.

Рис. 11.2. Созданный объект класса Dog

Рис. 11.3. Таблица виртуальных функций класса Mammal

Если в каком-то из объектов создается обычная не виртуальная функция, то всю полноту ответственности за эту функцию берет на себя объект. Большинство компиляторов создают таблицы виртуальных функций, называемые также v-таблицами. Такие таблицы создаются для каждого типа данных, и каждый объект любого класса содержит указатель на таблицу виртуальных функций (vptr, или v-указатель).

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

Рис. 11.4. Таблица виртуальных функций класса Dog

Итак, в каждом объекте есть указатель vptr, который ссылается на таблицу виртуальных функций, содержащую, в свою очередь, указатели на все виртуальные функции. (Более подробно указатели на функции рассматриваются на занятии 14.) Указатель vptr для объекта класса Dog инициализируется при создании части объекта, принадлежащей базовому классу Mammal, как показано на рис. 11.3.

После вызова конструктора класса Dog указатель vptr настраивается таким образом, чтобы указывать на замещенный вариант виртуальной функции (если такой есть), существующий для класса Dog (рис. 11.4).

В результате при использовании указателя на класс Mammal указатель vptr по- прежнему ссылается на тот вариант виртуальной функции, который соответствует реальному типу объекта. Поэтому при обращении к методу Speak в предыдущем

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

Нельзя брать там, находясь здесь

Если для объекта класса Dog объявлен метод WagTail, который не принадлежит классу Mammal, то невозможно получить доступ к этому методу, используя указатель класса Mammal (если только этот указатель не будет явно преобразован в указатель класса Dog). Поскольку функция WagTail не является виртуальной и не принадлежит классу Mammal, то доступ к ней можно получить только из объекта класса Dog или с помощью указателя этого класса.

Поскольку любые преобразования чреваты ошибками, создатели C++ допустили только явные преобразования типов. Всегда можно преобразовать любой указатель класса Mammal в указатель класса Dog, но есть более надежный и безопасный способ вызова метода WagTail. Чтобы разобраться в тонкостях упомянутого метода, необходимо освоить множественное наследование, о котором речь пойдет на следующем занятии, или научиться работе с шаблонами, что будет темой занятия 20.

Дробление объекта

Следует обратить внимание, что вся магия виртуальных функций проявляется только при обращении к ним с помощью указателей и ссылок. Если передать объект как значение, то виртуальную функцию вызвать не удастся. Эта проблема показана в листинге 11.10.

Листинг 11.10. Дробление объекта при передаче его как значения

1: //Листинг 11.10. Дробление объекта при передачи его как значения

2:

3: #include <iostream.h>

4:

5: class Mammal

6: {

7: public:

8: Mammal:itsAge(1) { }

9: virtual ~Mammal { }

10: virtual void Speak const { cout << "Mammal speak!\n"; }

11: protected:

12: int itsAge;

13: };

14:

15: class Dog : public Mammal

16: {

17: public:

18: void Speakconst { cout << "Woof!\n"; }

19: };

20:

21: class Cat : public Mammal

22: {

23: public:

24: void Speakconst { cout << "Meow!\ri"; >

25: };

26:

27: void ValueFunction (Mammal);

28: void PtrFunction (Mammal*);

29: void RefFunction (Mammal&);

30: int main

31: {

32: Mammal* ptr=0;

33: int choice;

34: while (1)

35: {

36: bool fQuit = false;

37: cout << "(1)dog (2)cat (0)Quit: ";

38: cin >> choice;

39: switch (choice)

40: {

41: case 0: fQuit = true;

42: break;

43: case 1: ptr = new Dog;

44: break;

45: case 2: ptr = new Cat;

46: break;

47: default: ptr = new Mammal;

48: break;

49: }

50: if (fQuit)

51: break;

52: PtrFunction(ptr);

53: RefFunction(*ptr);

54: ValueFunction(*ptr);

55: }

56: return 0;

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

Гридень 2. Поиск пути

Гуров Валерий Александрович
2. Гридень
Детективы:
исторические детективы
5.00
рейтинг книги
Гридень 2. Поиск пути

Попытка возврата. Тетралогия

Конюшевский Владислав Николаевич
Попытка возврата
Фантастика:
альтернативная история
9.26
рейтинг книги
Попытка возврата. Тетралогия

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Я – Стрела. Трилогия

Суббота Светлана
Я - Стрела
Любовные романы:
любовно-фантастические романы
эро литература
6.82
рейтинг книги
Я – Стрела. Трилогия

Инженер Петра Великого

Гросов Виктор
1. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Инженер Петра Великого

Колонист "Вано"

Сухов Лео
1. Антикризисный Актив
Фантастика:
героическая фантастика
попаданцы
7.17
рейтинг книги
Колонист Вано

Блуждающие огни 4

Панченко Андрей Алексеевич
4. Блуждающие огни
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Блуждающие огни 4

Возвышение Меркурия. Книга 8

Кронос Александр
8. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 8

Тринадцатый II

NikL
2. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый II

Девочка-яд

Коэн Даша
2. Молодые, горячие, влюбленные
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка-яд

Идеальный мир для Лекаря 28

Сапфир Олег
28. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 28

Имя нам Легион. Том 9

Дорничев Дмитрий
9. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 9

Ермак. Регент

Валериев Игорь
10. Ермак
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Ермак. Регент

Тигр под елку

Зайцева Мария
4. Наша
Любовные романы:
короткие любовные романы
5.00
рейтинг книги
Тигр под елку