Двоичное дерево - часть 13
class base {}
class aa : public base {}
class bb : public base {}
class cc : aa, bb {}
В классе cc присутствуют два объекта класса base. Для исключения такого дублирования объект базового класса должен быть объявлен виртуальным:
class a : virtual public base {}
class b : virtual public base {}
class c : public a, public b {}
a A1;
b B1;
c C1;
Объект обычного базового класса располагается, как правило, в начале объекта производного класса и имеет фиксированное смещение. Если же базовый класс является виртуальным, то требуется его динамическое размещение. Тогда в объекте производного класса на соответствующем месте размещается не сам объект базового класса, а указатель на него, который устанавливается конструктором. Для вышеприведенного примера получим такую картину:
Один из наиболее распространенных приемов использования виртуальных функции - создание базовых классов, объединяющих в единую группу различные классы на основе некоторого общего свойства. Базовый класс при этом заключает в себе общие свойства группы, а весь набор действий, которые одинаково применимы к объектам из любого класса, реализуется через виртуальные функции.
В качестве примера рассмотрим группу классов - типов данных. Допустим, проектируется база данных, предназначенная для хранения произвольных объектов (типов данных). Прежде всего, определяется ряд общих действий, которые обязательно должны быть выполнимы к объекте любого класса, чтобы он мог включаться в базу данных.
class ADT
{
public:
virtual int Get(char *)=0; // Загрузка объекта из строки
virtual char *Put()=0; // Выгрузка объекта в строку
virtual long Append(BinFile&)=0; // Добавить объект в двоичный файл
virtual int Load(BinFile&)=0; //
virtual int Type()=0; // Возвращает идентификатор
// типа объекта
virtual char *Name()=0; // Возвращает имя типа объекта
virtual int Cmp(ADT *)=0; // Сравнивает значения объектов
virtual ADT *Copy()=0; // Создает динамический объект -
// копию с себя
virtual ~ADT(){}; // Виртуальный деструктор