Documente Academic
Documente Profesional
Documente Cultură
Motenirea multipl:
Clase virtuale. Funcii
virtuale. Polimorfism.
Clase abstracte
Sumar
Derivata2
public: i
Derivata3
deriv1::i
deriv2::i
Ex.1b:
//acesta varianta de program foloseste explicit operatorul de declarare
#include<iostream.h>
class baza
{
public:
int i;
};
class derivata1:public baza
{
public:
int j;
};
class derivata2:public baza
{
public:
int k;
};
class derivata3:public derivata1,public derivata2
{
public:
int suma;
};
void main()
{
derivata3 ob;
ob.derivata1::i=10;
ob.j=20;
ob.k=30;
ob.suma=ob.derivata1::i+ob.j+ob.k;
cout<<ob.derivata1::i<<" ";
cout<<ob.j<<" "<<ob.k<<'\t';
cout<<ob.suma<<endl;
}
/*
Dupa cum se vede, deoarece s-a facut selectia (si anume derivata1 din baza) acest program ruleaza
normal.
Totusi, acesta solutie ridica o problema mai ampla: ce se intampla daca este ceruta efectiv doar o copie
pentru baza?
Exista vreo cale de a preveni includerea a doua copii in derivata3? Raspunsul este pozitiv, si anume
prin folosirea claselor vortuale.
Cand doua sau mai multe obiecte sunt derivate intr-o clasa de baza comuna, puteti preveni prezenta
intr-unul dintre acestea a mai multor copii ale clasei de baza, declarand-o virtual in momentul in care
ea este mostenita
*/
Ex.1c:
#include<iostream.h>
class baza
{
public:
int i;
};
class derivata1:virtual public baza
{
public:
int j;
};
class derivata2:virtual public baza
{
public:
int k;
};
class derivata3:public derivata1,public derivata2
{
public:
int suma;
};
void main()
{
derivata3 ob;
ob.i=10;
ob.j=20;
ob.k=30;
ob.suma=ob.i+ob.j+ob.k;
cout<<ob.i<<" ";
cout<<ob.j<<" "<<ob.k<<'\t';
cout<<ob.suma<<endl;
}
/* n acest exemplu fiecare din cele dou clase derivate intermediare motenesc clasa de
baz n mod virtual, ceea ce permite clasei derivate din final, derivata3, s moteneasc
ambele clase fr s mai apar probleme de ambiguitate. */
Funcii virtuale
S urmrim n ce const problema:
Fie o clas C1 care conine o metod M1 care o apeleaz pe o alta M2 din aceeai
clas. Pn aici nimic deosebit. O alt clas C2 o motenete pe prima. n cadrul acesteia
redefinim metoda M2, dar nu redefinim metoda M1. Declarm un obiect de tip C2 i
apelm metoda M1. Problema este urmtoarea: care va fi metoda apelat de M1, M2 din
Ex.2a:
#include<iostream.h>
class C1
{
public:
void M1()
{
M2();
}
void M2()
{
cout<<"unu "<<endl;
}
};
class C2:public C1
{
public:
void M2()
{
cout<<"doi "<<endl;
}
};
void main()
{
C1 x;
x.M1();
C2 y;
y.M1();
}
Aceast situaie poate fi remediat, adic s fie apelat metoda M2() redefinit.
Exist posibilitatea ca selecia s se fac n momentul apelului (nu la compilare). n astfel
de cazuri programatorul poate decide care metod s fie selectat. O selecie de acest tip
se numete selecie dinamic sau virtual.
Pentru a realiza selecia dinamic trebuie s procedm astfel:
orice redefinire a metodei (tipul retur al funciei i lista parametrilor trebuie s fie
identice), se face utiliznd acelai cuvnt cheie virtual acest lucru este
recomandat, nu neaparat obligatoriu.
Ex.2b:
#include<iostream.h>
class C1
{
public:
void M1()
{
M2();
}
virtual void M2()
{
cout<<"unu "<<endl;
}
};
class C2:public C1
{
public:
virtual void M2()
{
cout<<"doi "<<endl;
}
};
void main()
{
C1 x;
x.M1();
C2 y;
y.M1();
}
Polimorfism
Polimorfismul este legat de motenire, o particularizare a acesteia. Polimorfismul,
prin definiie, este capacitatea unui singur obiect de a lua forme diferite. Limbajul C++
accept polimorfismul prin intermediul funciilor virtuale. Cu ajutorul funciilor virtuale,
acelai pointer poate indica diferite clase pentru a realiza diferite operaii.
Ex.3:
#include<iostream.h>
#include<math.h>
class baza
{
public:
int add(int a,int b)
{
return a+b;
}
virtual int scad(int a,int b)
{
return a-b;
}
virtual int inmult(int a,int b)
{
return a*b;
}
};
class deriv1:public baza
{
public:
int inmult(int a,int b)
{
return a*b*2;
}
};
class deriv2:public baza
{
public:
int scad(int a,int b)
{
return abs(a-b);
}
};
void main()
{
Clase abstracte
n cele mai multe situaii, clasa de baz a unei ierarhii va trebui s fie foarte
general, elementele specifice rmnnd a fi ataate derivrilor acesteia. De fapt,
generalitatea clasei de baz poate atinge un astfel de grad nct aceast clas nici s nu
intervin n crearea obiectelor. Astfel de clase se numesc clase abstracte.
Clasele abstracte sunt nzestrate cu un tip special de funcii, virtuale pure. Pentru
a vedea cum se declar astfel de clase, vom considera exemplul urmtor. Aceast clas
conine funcii specifice, citire() i afisare(). Nedorind s definim aceste funcii n clasa
abstract, le vom face virtuale pure:
virtual void citire(int)=0;
virtual voi afisare(int)=0;
deci, vom iniializa numele lor, corpul ataat urmnd s fie implementat n clase derivate.
Abstractizarea trebuie neleas n adevratul sens al cuvntului, deoarece nu este
permis definirea de obiecte din astfel de clase. Trebuie create mai nti clase derivate din
acestea, n cadrul crora se vor redefini metodele virtuale pure. n cazul n care rmn
metode neimplementate, clasele derivate n aceast situaie rmn, n continuare,
abstracte. Cu toate c nu putem defini obiecte avnd ca tipuri clase abstracte, putem
defini pointeri ctre astfel de clase sau chiar referine.
Ex.4:
#include<iostream.h>
#include<stdio.h>
class abstract
{
public:
//functii virtuale pure
virtual void citire()=0;
virtual void afisare()=0;
};