Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Вторая часть лекции.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
592.9 Кб
Скачать

Void main()

{

cout << "ЧпОсновной базовый класс: sizeof(base) = " << sizeof(base);

cout << "^Непосредственная база: sizeof(dbase) = " << sizeof(dbase);

cout << "^Непосредственная база: sizeof(fbase) = " << sizeof(fbase);

cout << "ЧпПроизводный класс: sizeof(top) = " << sizeof(top); }

Результаты выполнения программы:

Основной базовый класс: sizeof(base) = 13

Непосредственная база: sizeof (dbase) = 23

Непосредственная база: sizeof(fbase) =19 Производный класс: sizeof(top) = 33

Основной базовый класс base в соответствии с размерами своих компонентов стандартных типов int и char [11] имеет размер 13 байт. Создаваемые на его основе классы dbase и fbase занимают соответ­ственно 23 и 19 байт. (В dbase входит переменная типа double, зани­мающая 8 байт, наследуется базовый класс base, для которого требуется 13 байт, и 2 байта нужны для связи в иерархии виртуальных классов.) Производный класс top включает: один экземпляр базового класса base (13 байт); данные и связи класса dbase (10 байт); данные и связи класса fbase (6 байт); компонент long tt (4 байта).

Если в той же программе убрать требование виртуальности (атрибут virtual) при наследовании base в классах dbase и fbase, то результаты будут такими:

Основной базовый класс: sizeof(base) = 13

Непосредственная база: sizeof(dbase) = 21

Непосредственная база: sizeof(fbase) = 17

Производный класс: sizeof(top) = 42

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

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

class X { ... } ;

class Y: virtual public X { ... }; class Z: virtual public X { ... }; class B: virtual public X { .. }; class C: virtual public X { ... }; class E: public X { ... ); class D: public X { ... }; class A: public D, public B, public Y, public Z, public C, public E { ... };

В данном примере объект класса а включает три экземпляра объ­ектов класса х: один виртуальный, совместно используемый классами в, Y, с, z, и два невиртуальных относящихся соответственно к классам D и е. Таким образом, можно констатировать, что виртуальность класса в иерархии производных классов является не свойством класса как такового, а результатом особенностей процедуры наследования.

Возможны и другие комбинации виртуальных и невиртуальных базовых классов. Например:

class ВВ { ... };

class АА: virtual public ВВ { ... };

class CC: virtual public ВВ { ... };

class DD: public AA, public CC, public virtual BB { ... };

Соответствующий НАГ имеет вид:

При использовании наследования и множественного наследования могут возникать неоднозначности при доступе к одноименным ком­понентам разных базовых классов. Простейший и самый надежный способ устранения неоднозначностей - использование квалифициро­ванных имен компонентов. Как обычно, для квалификации имени компонента используется имя класса. Следующий пример иллюстри­рует упомянутую неоднозначность и ее разрешение с помощью ква­лифицированных имен компонентов:

class X { public: int d; ... }; class Y { public: int d; ... }; class Z: public X, public Y, { public:

int d;

d - X::d + Y: :d; };