Rambler's Top100


Объектно-ориентированное программирование (Учебное пособие). Автор: Шахгельдян К.И. , редактор: Александрова Л.И.

5.4.4. Таблица виртуальных функций

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

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

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

Значения полей в таблице виртуальных функций – это указатели на методы. Поскольку процедуры известны компилятору и не изменяются во время выполнения, то таблица может быть статически во время компиляции. Чтобы выполнить метод, надо знать его смещение в таблице виртуальных функций.

Таблица виртуальных функций базового класса входит во все таблицы производных классов, а смещение методов в таблице базового класса будет тем же самым, что и в таблицах производных классах.

class Base {

         int x;

public:

         virtual void print();

};

class Derived1: public Base {

         int y;

public:

         virtual void print();

         void get();

};

Предположим, что vtab – это внутреннее имя поля, представляющее указатель на таблицу виртуальных функций в объекте x, и что смещение для метода print() равно 10. Тогда вызов метода

x.print(y);

будет преобразован в следующее внутреннее представление

(*(*(x.vtab))[10])(x,y);

Объект x доступен как первый аргумент в списке параметров.

В литературе [1,5] вы можете получить дополнительную информацию о таблице виртуальных функций.

Советы

1.  Пользуйтесь абстрактными классами в С++ и интерфейсами в Java для отделения интерфейса от реализации.

2.  Пользуйтесь виртуальными функциями в С++, чтобы можно было добавлять новые классы, не меняя ранее написанный код.

3.  В классе с виртуальной функцией стоит иметь виртуальный деструктор.

4.  Абстрактный класс обычно не нуждается в конструкторе.

5.  Пользуйтесь контрольными листами.

6.  Всегда определяйте в классе конструктор копирования, виртуальный деструктор, операцию присваивания, если в классе динамически выделяется память, запрашивается ресурс.

7.  Не вызывайте конструктор в перегруженном операторе присваивания. Скорее всего, он не будет работать при порождении.

Упражнения для самопроверки

Заполните пробелы в следующих утверждениях:

1. Отношения между классами "содержит" представляет _________ , а отношение "является" представляет          .

2. Чисто виртуальная функция задается с помощью размещения
_________  в конце ее прототипа в определении класса.

3. Если класс содержит хотя бы одну чисто виртуальную функцию, то класс называется       .

4. Вызов функции, обрабатываемый во время компиляции, называется        связыванием.

5. Вызов функции, обрабатываемый во время выполнения программы, называется  связыванием.

6. Как в Java описываются виртуальные функции.

7. Верно ли утверждение: все виртуальные функции в абстрактном базовом классе должны быть чисто виртуальными.

8. Производный класс, полученный закрытым наследованием, не является подтипом базового класса?

9. Производный класс, полученный защищенным наследованием, не является подтипом базового класса?

10. Подтип всегда равен подклассу?

11. Подкласс всегда равен подтипу?

Задания

1.  При наличии классов Circle (круг), Square (квадрат) и Triangle (треугольник), производных от Shape (фигура), определите функцию intersect() (пересечение), которая принимает две фигуры Shape* в качестве аргументов и вызывает подходящие функции для определения того, пересекаются ли эти фигуры. Не пишите код, проверяющий пересечение; просто убедитесь, что вызываются правильные функции.

2.  Рассмотрите классы точка (Point), окружность (Circle), цилиндр (Cylinder) с точки зрения наследования и композиции. Отметьте сильные и слабые стороны обоих подходов.

3.  Что такое виртуальная функция и каковы преимущества ее использования?

4.  Выявите различия между статическим и динамическим связыванием. Объясните использование таблиц виртуальных методов.

5.  В чем разница между наследованием интерфейса и наследованием реализаций.

6.  Каким образом в Java реализуется механизм абстрактных базовых классов и общего интерфейса. В чем разница между абстрактным классом и интерфейсом?

7.  Объясните, почему полиморфное программное обеспечение будет эффективно при решении задачи отображения различных графических объектов?

8.  Разработайте иерархию типов для всех двумерных и трехмерных форм, которые Вы можете придумать.

9.  Сравните преимущества и недостатки композиции и наследования.

10. Объясните необходимость виртуальных деструкторов

11. В чем разница между замещением и уточнением.

12.   Как, по-вашему, должны работать виртуальные функции в конструкторе и деструкторе.

Литература

1.  Бадд Т. Объектно-ориентированное программирование в действии. СПб.: Питер, 1997. Гл. 9, 10, 14.

2.    Страуструп Б. Язык программирования С++. 3-е изд. М.: Бином. с. 358-376.

3.  Дейтел Х.М., Дейтел П.Дж. Как программировать на С++. М.: Бином, 1998. с. 574-575, 595-628.

4.  Шилдт Г. Самоучитель С++. СПб.: bhv, 1997. Гл. 10.

5.  Пол И. Объектно-ориентированное программирование с использованием С++. Киев: Диасофт, 1995. с. 282-291.

6.  Томас М., Пател П., Хадсон А., Болл Д. Секреты программирования для Internet на Java. СПб.: Питер пресс, 1997. с. 102-110.

7.  Flangan D. Java in Nutshell. O'Reilly. 1997. Ch. 3.7, 3.9.

8.  Grand D. Java language reference. O'Reilly. 1997. Ch. 5.4, 5.5.

9.  Niemeyer P., Peck J. Exploring Java. O'Reilly. 1997. Ch. 5.8.

Poker razz odds calculator