Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++.docx
Скачиваний:
19
Добавлен:
10.06.2015
Размер:
95.05 Кб
Скачать

62. Множественное наследование.

Наследование является множественным, если при производном классе указывается 2 или более базовых классов. Синтаксис определим примером:

class x1 {…};

class x2 {…};

class x3 {…};

class y: public x1, protected x2, x3 {…}; // здесь класс y наследует элементы 3-х классов, каждый из 3-х базовых классов должен быть указан со своим спецификатором, может быть неявно. Схема этой иерархии классов такова:

x1

x2

x3

y

Рис. 4.2 «Пример множественного наследования»

Один и тот же класс может быть непрямым базовым классом у данного производного класса

Пример:

class x {long double ax};

class y1: public x {double ay1};

class y2: public x {int ay2};

class z: public y1, public y2 { };

Схема иерархии:

x

x

z

y1

y2

Рис. 4.3 «пример множественного наследования с многократным использованием класса x в качестве непрямого базового»

Соответствующие объемы этих классов будут такими:

size (X) = 10 байт (long double)

size (Y1) = 18байт (long double + double)

size (Y2) = 14байт (long double + int)

size (Z) = 32байта (long double + long double + double + int)

таким образом ax класса X дважды будет повторяться Z, так как имя поля в обеих ветвях наследования наследования одинаково, то при обращении к конкретному полю необходимо указывать по какой ветви прошло наследование

Z:: Y1:: X:: ax // наследование через класс Y1

Z:: Y2:: X:: ax // наследование через класс Y2

Если по запланированной логике построения иерархии классов повторение поля ax является лишним, то необходимо объявить, что класс X наследуется как виртуальный, то есть объявление должно иметь вид:

class Y1: virtual public X {double ay1}

class Y2: virtual public X {double ay2}

Объявленные при этом X и Z не меняются. На схемах такое наследование изображается в виде ромбовитых диаграмм:

Y1

X

Z

Y2

Рис. 4.4 «Пример виртуального наследования класса X»

Виртуальное наследование обеспечивается благодаря тому, что компилятор добавляет по еще одному полю Y1, Y2 – это указывает на виртуальный базовый класс. Зная этот класс компилятор исключает дублирование полей непрямого базового класса, поэтому размеры классов будут такими:

size (X) = 10байт (long double)

size (Y1) = 22байта (long double + double + X*) // добавляется указатель X

size (Y2) = 18байт (long double + int + X*)

size (Z) = 30байт (long double + double + int + X* + X*) // лишнее поле long double исчезло, но появилось два указателя поля, унаследованные от прямых базовых классов Y1 и Y2

Таким образом, в общем случае объект производного класса определяется с виртуальным наследованием, включая в себя базовый класс, указатель на объект базового класса. Если в свою очередь 2 или более производных класса Y1 и Y2 становятся базовыми для 3-го уровня Z, то поля непрямого базового класса не дублируются, но указывают наследника от всех прямых базовых классов Y1 и Y2.

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

class X {long double ax};

class Y1: virtual public X {double ay1};

class Y2: virtual public X {double ay2};

class Y3: public X {int ay3};

class Z: public Y1, public Y2, public Y3 { };

Схема иерархии такова:

X

Y1

Y2

Z

Y3

X

Рис. 4.5 «Пример смешанного наследования класса X»

Размеры объектов таковы:

size (Y1) = 22байта (long double + double + X*)

size (Y2) = 18байт (long double + int + X*)

size (Y3) = 14байт (long double + int)

size (Z) = 44байта (long double + double + int + X* + X* + long double + int)

Особое определение и применение специальных методов в производном классе:

В С++ относ. спец. методы:

  • конструктор умолчания

  • конструктор копирования

  • деструктор

  • функция операция присваивания

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]