Sunteți pe pagina 1din 40

Programare orientat obiect

Curs 8

Motenirea multipl

Motenirea multipl
Limbajul C++ permite derivarea unei clase din dou sau mai multe clase de baz Se realizeaz astfel o structur de tip reea ce nu aduce ntotdeauna numai beneficii n limbajele puternic orientate obiect (C#, Java) motenirea multipl este evitat prin forarea derivrii doar din maxim o clas i mai multe interfee

Exemplu
class A {}; class B {}; class C {}; class D : public A, private B, protected C {};

Precizri
Constructorul clasei D trebuie s specifice explicit colaborare cu ceilali constructori din clasele de baz Ex: D::D() : A(), B(), C() {} n mod similar se procedeaz i pentru constructorul cu parametri i cel de copiere

Precizri
n cazul n care constructorul clasei D lipsete este creat automat unul sintetizat din constructorii de baz n acest fel fiecare constructor din baz i iniializeaz zona lui de obiect Constructorii sunt apelai n ordinea specificat la derivare (nu n cea din definiia constructorului) Destructorii se apeleaz n ordine invers derivrii

when I encounter the diamond class inheritance problem


sursa foto: http://thecodinglove.com/post/63643925743/when-i-migrate-a-project-from-visual-studio-2005-to

Probleme ce apar la motenirea multipl


Problema membrilor motenii cu acelai nume Problema motenirii multiple din clase cu o baz comun

Problema membrilor motenii cu acelai nume


n general este rezolvat prin utilizarea rezoluiei de clas ori de cte ori membrul motenit este referit n cazul funciilor se poate opta i pentru redeclararea funciei comune n clasa derivat (folosind alt cod sau apelnd una din funciile din baz)

Problema membrilor motenii cu acelai nume


Clasa de baz 1

Problema membrilor motenii cu acelai nume


Clasa de baz 2

Problema membrilor motenii cu acelai nume


Clasa derivat i rezolvarea ambiguitii

Problema motenirii multiple din clase cu o baz comun

A
B D C

Problema motenirii multiple din clase cu o baz comun


Problema este dat de faptul c D va moteni membrii clasei A de dou ori Dac acest lucru este dorit, atunci clasele pot rmne aa Dac nu, putem rezolva problema prin utilizarea conceptului de motenire virtual

Alte precizri
Upcasting-ul n cazul motenirii multiple este permis din oricare din clasele derivate ctre clasa de baz A *pa; B *pb; D d; pa = &d; pb = &d; Upcasting-ul n cazul motenirii multiple din clase cu o baz comun trebuie fcut etapizat A *pa; D d; pa=&d; //eroare A *pa; B *pb; D d; pb = &d; pa = pb;

Funcii virtuale

when I try to get rid of virtual functions


sursa foto: http://d24w6bsrhbeh9d.cloudfront.net/photo/awrMY8W_460sa.gif

Funciile virtuale
Implementeaz cea de-a doua form de polimorfism Prima form de polimorfism era suprancrcarea (overloading) Aici vorbim de conceptul de supradefinire (overriding) Nu pot fi statice

Overloading vs Overriding
La overloading alegerea funciei potrivite se face la compilare (early binding), n cazul overriding-ului se face la execuie (late binding) La overloading alegerea funciei potrivite se face n funcie de prototip (numrul i tipul parametrilor), n cazul overriding-ului se face n funcie de obiectul pointat

Overloading vs Overriding
Putem vorbi de overloading doar n cadrul aceleiai clase, iar de overriding doar atunci cnd lucrm cu clase derivate Avem de-a face cu overriding doar atunci cnd folosim funcii virtuale (rescrierea funciilor n clase derivate, fr specificarea cuvntului cheie virtual n clasa de baz, nu este considerat supradefinire)

Exemplul 1
Clasa de baz

Exemplul 1
Clasa derivat 1

Exemplul 1
Clasa derivat 2

Exemplul 1
Utilizare funcii virtuale

Exemplul 1
Utilizare funcii virtuale

Exemplul 2
Funcie global ce utilizeaz referin la clasa de baz

Exemplul 2
Apel i rezultat

Funciile virtuale pure


Au prototipul: virtual tip nume (parametri) = 0; Oblig clasele ce motenesc clasa n care exist s o implementeze (neimplementarea duce la eroare de compilare) O clas ce are cel puin o funcie virtual pur se numete clas abstract

Clasele abstracte
Nu pot fi instaniate (nu putem declara obiecte de tipul clasei respective) Acest lucru nu nseamn c nu putem declara pointeri ctre clasa respectiv n care s salvm adrese de obiecte din clase derivate (upcasting) pentru a implementa virtualizarea

Clasele abstracte
Implementeaz comportamente n general Constituie baz pentru derivri n limbajele de programare orientate obiect mai noi au fost nlocuite cu noiunea de interfa (exemple de nume de interfee n C#: IComparable, ICloneable)

Derivare virtual

when I hear the world virtual again

sursa foto: http://thecodinglove.com/post/58435172557/when-i-am-going-to-home-on-friday-night

Derivarea virtual
Utilizat pentru a nu moteni n duplicat membrii clasei de baz n cadrul ierarhiei de tip romb Se utilizeaz pentru clasele derivate din baz i are efect asupra claselor derivate din acestea Clasele derivate virtual se numesc clase virtuale (fr legtur cu acele clase ce conin funcii virtuale sau virtuale pure)

Exemplu
Clasa mam (A)

Exemplu
Clasa derivat 1 (B)

Exemplu
Clasa derivat 2 (C)

Exemplu
Clasa final (D)

Exemplu
Ce credei c afieaz codul?

Exemplu
Rspuns:

Precizri finale
Dac folosim derivare virtual upcasting-ul poate fi fcut direct de la clasa final ctre baz (nu mai e nevoie de etapizarea lui) n cazul n care clasa de baz conine o funcie virtual sau virtual pur, aceasta trebuie obligatoriu implementat n clasa final (altfel aceasta motenete dou implementri ale funciei virtuale, ambele pe acelai nivel, compilatorul semnalnd ambiguitate)