Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву
Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Множественное наследование. Виртуальный базовый классСодержание книги
Поиск на нашем сайте Прямые базовые классы Множественное наследование имеет место, если список порождения содержит более одного базового класса. Например,
class C: public A, public B {....};
То есть схематично это выглядит так:
Функции, определенные в классах A и B в части public, доступны объекту класса C независимо от того, в каком классе они определены.
С x(...); // действует конструктор класса A, потом B, потом C x.Fa(); x.Fb();
Операция:: здесь не требуется, так как функции имеют разные имена. А если в классах A и B имелась бы функция с одинаковым именем, например, F(), то обращение к ней с объектом класса C должно содержать операцию::
x.A:: F(); или x.B:: F();
Конструктор класса C отвечает за инициализацию член-данных классов A и B, то есть должен иметь, например, такой вид:
C:: C(int x, int y, int z): A(x), B(y) {c = z;}
Рассмотренный пример – это пример множественного наследования с прямыми базовыми классами. Если же базовые классы A и B в свою очередь порождены от других базовых, то эти последние для класса C будут не прямыми базовыми (или косвенными). Приведем пример такого наследования.
Виртуальный базовый класс В случае косвенных базовых классов может возникнуть ошибочная ситуация. Рассмотрим, в чем она заключается. Пусть, например, имеется такая иерархия порождения
Рассмотрим пристальнее, что означает такое наследование: Эта схема показывает, что объект класса D будет содержать 2 копии член-данного int a класса A, что может привести к двусмысленности. Например, если в классе D есть функция
int D:: Geta() {return a;}
и член-данное a находится в части protected класса A, то компилятор все равно выдаст сообщение об ошибке – «двусмысленность»: так как непонятно член-данное a надо взять из части B:: A или C:: A. Избежать двусмысленности можно, указав явно класс B или C.
int D:: Geta() {return C:: a;}
Однако наличие в дереве наследования нескольких копий одного и того же базового класса не только вносит путаницу, но и приводит к лишним затратам памяти. Чтобы этого не происходило, базовый класс A в списке порождения надо объявить виртуальным: class B: public virtual A {...}; class C: public virtual A {...}; class D: public B, public C {...};
В этом случае в объектах классов B и C будут сформированы указатели на член-данные базового класса A. То есть картина будет такой:
Из рисунка видно, что в данном случае неоднозначности для член-данного a не будет, так как a – одна ячейка! Замечание. В рассмотренных двух способах порождения класса D: 1) не через виртуальный базовый класс A; 2) через виртуальный базовый класс A конструктор класса D определяется по-разному. В первом случае конструктор класса D не «заботится» об инициализации член-данных класса A, то есть определяется, например, так
D(int r, int s): B(r), C(s) {...}.
А во втором случае конструктор класса D отвечает и за инициализацию член-данных виртуального базового класса A. То есть должен быть задан, например, так
D(int r, int s, int q): A(r), B(s), C(q) {...}
В заключение рассмотрим пример наследования: порождение класса Kolobok из двух базовых классов Bar и Circ из п. 12 главы 1.
const int CF = 7; class Bar { protected: int h, w, x, y; public: Bar(int hh, int ww, int xx, int yy) {h = hh; w = ww; x = xx; y = yy;} void Show(int c) { } };
class Circ { int r; protected: int x, y; public: Circ(int rr, int xx, int yy) {r = rr; x = xx; y = yy;} void Show(int c) { } };
class Kolobok: public Circ, public Bar { int numb; char * name; // место и имя public: Kolobok(int h, int w, int x, int y, int r, int m, char * s): Bar(h, w, x, y), Circ(r, x + w / 2, y - r) {numb = m; name = new char [strlen(s) + 1]; strcpy(name, s); } ~Kolobok() {delete [ ] name;} void Show(int cb, int cc, int ck) {Bar:: Show(cb); Circ:: Show(cc); … } };
void main() {int x = 200, dx = 100, i; Kolobok klb[3] = {Kolobok(100, 50, x, 150, 40, 2, “два”), Kolobok(150, 50, x = x + dx, 100, 35, 1, “один”), Kolobok(50, 50, x = x + dx, 200, 30, 3, “три”) }; for(i = 0; i < 3; i++) klb[i].Show(4, 14, 12); Kolobok *pbc = new Kolobok(50, 50, 300, 400, 50, 4); pbc –> Show(3, 12, 14); delete pbc; }
|
||
|
Последнее изменение этой страницы: 2021-12-07; просмотров: 106; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.236 (0.009 с.) |