
- •Базовые принципы объектно-ориентированного программирования.
- •Базовые конструкции объектно-ориентированных программ.
- •Конструктор и деструктор. Конструктор по умолчанию.
- •Конструктор копирования.
- •Конструктор explicit.
- •Указатель this.
- •Абстрактные типы данных.
- •Операторы для динамического выделения и освобождения памяти (new и delete).
- •Перегрузка и переопределение функций.
- •Перегрузка бинарных операторов.
- •Перегрузка унарных операторов.
- •19.20.Перегрузка оператора new.Перегрузка оператора delete.
- •22.Inline-функции.
- •23.Вложенные классы
- •24.Static-компоненты данные класса
- •25.26.Static и const-компоненты функции класса
- •27.Использование new delete для реализации массивов
- •28.Организация внешнего доступа к локальным компонентам класса(friend)
- •29.Ссылки.Параметры ссылки
- •30.Ссылки.Независимые ссылки
- •31.Инициализация компонент-данных объекта. Конструктор с параметрами.
- •33.Наследование. Открытое, защищенное и закрытое.
- •34.Виртуальные функции.
- •35.Множественное наследование.
- •36.Множественное наследование и виртуальные базовые классы
- •38.Proxi-классы.
- •39.40.Пространство имен. Пространство имен как объявление. Пространство имен как директива.
- •41.Виртуальные функции
- •42.Параметризированные классы (шаблоны).
- •43.Шаблоны функций.
- •44.Передача в шаблон класса дополнительных параметров.
- •44.Совместное использование шаблонов и наследования.
- •45.Шаблоны класса и friend.
- •46.Реализация smart-указателя.
- •48.Транзакции.
35.Множественное наследование.
В языке С++ имеется возможность образовывать производный класс от
нескольких базовых классов. Общая форма множественного наследования имеет вид class имя_произв_класса : имя_базового_кл 1,…,имя_базового_кл N { содержимое класса };
Иерархическая структура, в которой производный класс наследует от не-
скольких базовых классов, называется множественным наследованием. В этом случае производный класс, имея собственные компоненты, имеет доступ к protected- и public-компонентам базовых классов.
Конструкторы базовых классов при создании объекта производного клас-
са вызываются в том порядке, в котором они указаны в списке при объявлении производного класса. При применении множественного наследования возможно возникновение нескольких конфликтных ситуаций. Первая − конфликт имен методов или атрибутов нескольких базовых классов:
class A
{public: void fun(){}
};
class B
{public: void fun(){}
};
class C : public A, public B
{ };
int main()
{ C *c=new C;
c->fun(); // error C::f' is ambiguous
return 0;
}
При таком вызове функции fun() компилятор не может определить, к ка-
кой из двух функций классов A и B выполняется обращение. Неоднозначность можно устранить, явно указав, какому из базовых классов принадлежит вызываемая функция: c->A:: fun(); или c->B::fun();
Вторая проблема возникает при многократном включении некоторого
базового класса:
#include <iostream>
using namespace std;
#include <string.h>
class A // базовый класс I уровня
{ char naz[20]; // название фирмы
public:
A(char *NAZ) {strcmp(naz,NAZ);}
~A() {cout << "деструктор класса А" << endl;}
void a_prnt() {cout << naz << endl;}
};
class B1 : public A // производный класс (1 Базовый II уровня)
{ protected:
long tn;
int nom;
public:
B1(char *NAZ,long TN,int NOM): A(NAZ),tn(TN),nom(NOM) {};
~B1() {cout << "деструктор класса В1" << endl;}
void b1_prnt()
{ A::a_prnt();
cout << " таб. N " << tn <<" подразделение = " << nom <<endl;
}
};
class B2 : public A // производный класс (2 Базовый II уровня)
{ protected:
double zp;
public:
B2(char *NAZ,double ZP): A(NAZ),zp(ZP) {};
~B2(){cout << "деструктор класса В2" << endl;}
void b2_prnt()
{ A::a_prnt();
cout << " зар/плата = " << zp << endl;
}
};
class C : public B1, public B2 // производный класс ( III уровня)
{ char *fam;
public:
C(char *FAM,char *NAZ,long TN,int NOM,double ZP) :
B1(NAZ,TN,NOM), B2(NAZ,ZP)
{ fam = new char[strlen(FAM)+1]
strcpy(fam,FAM);
};
~C() {cout << "деструктор класса С" << endl;}
void c_prnt()
{ B1::b1_prnt();
B2::b2_prnt();
cout << " фамилия " << fam<<endl;
}
};
int main()
{ C cc("Иванов","мастра",1234,2,555.6),*pt=&cc;
// cc.a_prnt(); ошибка 'C::a_prnt' is ambiguous
// pt->a_prnt();
cc.b1_prnt();
pt->b1_prnt();
cc.b2_prnt();
pt->b2_prnt();
cc.c_prnt();
pt->c_prnt();
return 0;
}
В приведенном примере производный класс С имеет по цепочке два оди-
наковых базовых класса А (A<-B1<-C и A<-B2<-C), для каждого базового класса А строится свой объект (рис. 3, 4). Таким образом, вызов функции
cc.a_prnt(); pt->a_prnt();некорректен, так как неизвестно, какую из двух функций (какого из двух классов А) требуется вызвать.