Программирование >>  Программирование на языке c++ 

1 ... 45 46 47 [ 48 ] 49 50 51 ... 159


ром ОНИ объявлены впервые. В результате их можно использовать даже тогда, когда у этого класса нет производных классов. С другой стороны, производный класс может либо переопределять виртуальную функцию, либо не переопределять ее. Более детально метод вызова виртуальных функций можно пояснить следующим образом. Когда конструируется (создается) новый объект, для него выделяется память. Для виртуальных функций (и только для них) в этой памяти выделяется место, где хранится указатель на таблицу функций, из которой на этапе выполнения программы будет выбираться нужная функция. Доступ к виртуальной функции осуществляется через этот указатель и соответствующую таблицу (т. е. здесь имеет место косвенный вызов функции, см. прил. 2.2).

Если некоторая функция вызывается с использованием ее полного имени, например:

book::display();

то виртуальный механизм игнорируется. Мы использовали эту особенность выше в примере. Здесь следует обратить внимание на возможную серьезную ошибку. Давайте изменим приведенную выше функцию:

void programmers guide::display(void)

{ displayO;

cout programming language used endl;

В этом случае строка displayO; вызывает эту же функцию (саму себя) и возникает бесконечная рекурсия.

Заметим, что деструктор может быть виртуальным, а конструктор - нет.

На рис. 4.2 приведены правила вызова виртуальных функций через указатели на объекты базового и производного классов.

Рассмотрим примеры. Первая программа показывает передачу указателей на объекты базового и производного классов в функцию f(...) и вызов через эти указатели виртуальной функции displayO.

#include <iostream.h> class A { базовый класс int a;



public:

A(int аа) : а(аа) {} конструктор

virtual void displayO { cout endl a; }

class В : public A { производный класс

int b; public:

B(int aa, int bb) : A(aa), b(bb) {} конструктор void displayO { A::displayO;

cout \t b; }

void f(A* x) { x->display(); void main(void)

A a1(33),a2(44);

Bb1(1,2),b2(11,12);

f(&a1); Результат: 33

f(&a2); Результат: 44

f(&b1); Результат: 1

базовый класс


p - указатель на объект базового класса U 1

р - получает значение указателя на объект базового класса


р - получает значение указателя на объект производного класса

I р - > displayO; I

вызов этой

функции

Рис. 4.2. Вызов виртуальных функций через указатели на объекты базового и производного классов



f(&b2); Результат: 11 12

Вторая программа демонстрирует построение списка книг (некоторые из них являются руководствами для программиста) и вывод информации о книгах с использованием виртуальной функции display(). Заметим, что функция displayO выводит больше информации о руководстве для программиста, чем просто о книге.

#include <iostream.h> class book { базовый класс char *title; заголовок книги

book *next; указатель на следующую книгу в списке static book *list; используется для построения списка книг public:

book{char *t) : title(t){ next = list; list = this; } virtual void displayO const { cout << endl title; } static void display list();

void book::display listO { выводит список книг

for(book* p=list;p;p=p->next) p->display(); } book* book::list = NULL; сначала список не содержит книг class programmers guide: public book { производный класс

int level; уровень знаний программиста public:

programmers guide(char *t,int I) : book(t), level(l) {} void displayO const { book::displayO;

cout \t level endl; }

void main(void)

{ book bICthe first book ), b2( the second book ); programmers guide pg1( the first guide ,5); book b3( the third book ); programmers guide pg2{ the second guide ,12); book::display listO;



1 ... 45 46 47 [ 48 ] 49 50 51 ... 159

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