Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Множественное наследование и виртуальные базовые классы




Класс называют непосредственным (прямым) базовым классом (прямой базой), если он входит в список базовых при определении класса. В то же время для производного класса могут существовать косвенные или непрямые предшественники, которые служат базовыми для классов, входящих в список базовых. Если некоторый класс A является базовым для B и B есть база для C, то класс B является непосредственным базовым классом для C, а класс A - непрямой базовый класс для C (рис. 8.2). Обращение к компоненту ха, входящему в A и уна­следованному последовательно классами B и C, можно обозначить в классе с либо как А::ха, либо как В::ха. Обе конструкции обеспечи­вают обращение к элементу ха класса A.

Рис. 8.2. Прямое и косвенное наследование классов

 

Иерархию производных классов удобно представлять с помощью направленного ациклического графа (НАГ), где стрелкой изображают отношение "производный от". Производные классы принято изображать ниже базовых. Именно в таком порядке их объявления рассматривает компилятор и их тексты размещаются в листинге программы. Класс может иметь несколько непосредственных базовых классов, т.е. может быть порожден из любого числа базовых классов, например,

class X1 {…};

class X2 {…};

class X3 {…};

class Y1: public X1, public X2, public X3 {…};

 

Наличие нескольких прямых базовых классов называют множественным наследованием. При множественном наследовании никакой класс не может больше одного раза использоваться в качестве непосредственного базового. Однако класс может больше одного раза быть непрямым базовым классом:

class X{ public: int a; int f();};

class Y: public X{…};

class Z: public X{…};

class D: public Y, public Z{…};

  

В данном примере класс Х дважды опосредованно наследуется классом D. Особенно хорошо это видно в направленном ациклическом графе (НАГ):

Проиллюстрированное дублирование класса соответствует включению в производный объект нескольких объектов базового класса. В нашем примере существуют два объекта класса Х, и поэтому для устранения возможных неоднозначностей вне объектов класса D нужно обращаться к конкретному компоненту класса Х, используя полную квалификацию: D::Y::X::f() или D::Z::X::f(). Внутри объекта класса d обращения упрощаются: У::Х::f() или Z::X::f(), но тоже содержат квалификацию.

В качестве примера рассмотрим класс Heir из предыдущего параграфа. Он является производным от классов Square и ClsEllipse. В свою очередь Square и ClsEllipse являются производными от класса Figura. Направленный ациклический граф для класса Heir будет выглядеть следующим образом.

Figura                                                                                        Figura

                           Square                               ClsEllipse

                                             Heir

 

Как видим в класс Heir входит два объекта типа Figura. Это значит, что в Heir будет две копии всех не статических компонентных данных класса Figura и компонентным функциям этого класса можно будет обратиться, например, либо через Heir::Square::Figura::display(), либо через Heir::ClsEllipse::Figura::display().

Чтобы устранить дублирование объектов непрямого базового класса при множественном наследовании, этот базовый класс объявляют виртуальным. Для этого в списке базовых классов перед именем класса необходимо поместить ключевое слово virtual. Например, класс Х будет виртуальным базовым классом при таком описании:

 

class X { public: int a; int f();};

class Y: virtual public X{…};

class Z: virtual public X{…};

class D: public Y, public Z{…};

 

Теперь класс D будет включать только один экземпляр X, доступ к которому равноправно имеют классы Y и Z. Графически это очень наглядно:

 

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

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{…};

 

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

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

class ВВ{…};

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

class CC: virtual public ВВ{…};

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

 

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

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

class X { public: int d; … };

class Y { public: int d; … };

class Z: public X, public Y {

public:

     int d;  

     void f(){d - X::d + Y::d;}

 };





Поделиться с друзьями:


Дата добавления: 2018-10-15; Мы поможем в написании ваших работ!; просмотров: 585 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Есть только один способ избежать критики: ничего не делайте, ничего не говорите и будьте никем. © Аристотель
==> читать все изречения...

4261 - | 4180 -


© 2015-2026 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.