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

12. Множинне наслідування.

Класс может иметь более одного непосредственного базового класса, т.е. после « : » в объявлении класса может быть указано несколько классов. Использование более одного непосредственного базового класса наз множественным наследованием. Наличие одного базового класса наз одиночным наследованием.

Непосредственный базовый класс – это класс, который явл базовым для данного класса.

Косвенный базовый класс – это такой базовый класс, который для данного класса явл или непосредственным базовым классом, или явл базовым для другого базоваого класса.

Класс не может иметь 2 одинаковых непосредственных базовых класса.

class l{int next;…]class a:public l{};class b:public l{};class c:public a,public b{};

Неоднозначность: void c:f(){a::next=0; b::next=0;}

При множественном наследовании неявное преобразование указателя запрещено.

Приведение указателей при мн.наслед.

Неявное преобразование: C *pc=new C; L *pl; pl=pC;//Err pl=(L*)pc;//Err pl=(A*)pc; pl=(L*)(A*)pc;

Явное преобразование: //“manager<-employee” //pm=(manager*)pc; pc=pl; //Err pc=(c*)pl;//Err pc=(c*)(b*)pl;

Разрешение неоднозначности при вызове функции базового класса при мн.наслед.

Два базовых класса могут иметь фн-члены с одинаковым именем. Пример: class A{virtual type* f();}; class B{virtual type* f();}; class C:public A,public b{};. При использовании С эти неоднозначности должны быть устранены: void mainf(C* pc){type* tp=pc->f(); //ошибка – неоднозначно tp=pc->A::f();tp=pc->B::f();}

Однако, явное устранение неоднозначности неудобно, поэтому лучше разрешить эти проблемы, определив новую функцию в производном классе: class C:public A,public B{type* f(){type* tp1=A::f(); type* tp2=B::f(); return tp1->merge(tp2);}};

Это локализует информацию о базовых классах С.

Пример1: info (тип) *{{L A B C}}::f(); //фн f есть в каждом классе; info *C::f(){ info *pi1=A::f(); //явно вызываем функцию info *pi1=B::f(); return merge(pi1,pi2);//слияние информации}

Пример2: class Employee{public: void f();} class Manager:public Employee {public:void f();} void Manager::f(){Employee::f();}

class Foreman:public Employee{public: void f();}; class Manager:public Foreman {public: void f();}; class Foreman:public Employee {typedef Employee inherited; public: void f() {inherited::f();…}}; class Manager:public Foreman {typedef Foreman inherited; public: void f(){inherited::f();…}}; //вызов функции f с Foreman. Если изменять, то только в одном месте.

13. Виртуальные базовые классы.

virtual – фактический.

Все части объекта должны совместно использовать единственную копию базового класса, в противном случае неоправданно сложно становиться избегать хранения нескольких копий объекта. Одним из механизмов задания такого совместного использования является виртуальный базовый класс. Каждый виртуальный базовый класс в производном классе представлен одним и тем же (совместно используемым) объектом. Например: class A{}; class B:public virtual A{};class C:public virtual A{};class D:public B,public C{};

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

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

Может иметь место ситуация, когда какой-то класс входит в иерархию наследования и как вирт, и как невирт.

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