/******************************************************************************/
class Student
{
int m_Id;
char *m_Nume;
int m_Note[100]; /* lista de note (prima valoare 0 => finalul listei) */
public:
Student (int id, char *nume, int note[]);
Student (const char *stdinfo); /* init std pe baza unui sir formatat */
/******************************************************************************/
Student::Student (int id, char *nume, int note[]) : m_Id(id)
{
this->setNume (nume);
int step = 0;
char *p = strtok (linfo, ",");
while (p != NULL)
{
switch (step) {
case 0:
m_Id = atoi (p); break;
case 1:
this->setNume (p); break;
default:
this->addNota (atoi(p));
};
if (nume == NULL)
return;
if (m_Nume != NULL)
delete[] m_Nume;
float Student::getMedie () {
int i;
float s = 0;
for (i = 0; i < sizeof(m_Note) / sizeof(int) && m_Note[i] != 0; i++)
s = s + m_Note[i];
void Student::print () {
std::cout << "id: " << m_Id;
std::cout << "\nnume: " << m_Nume;
std::cout.precision (2);
std::cout << "\nmedie: " << std::fixed << this->getMedie() << std::endl;
}
int i = 0;
while (i < sizeof(m_Note)/sizeof(int) && m_Note[i] != 0) i++;
/******************************************************************************/
void main ()
{
/* Instantiem un std cu id=101, nume=Ionescu Vasile, notele 8,9,5,... */
Student S1 ("101,Ionescu Vasile,8,9,5,10,8,9");
S1.print();
Daca ne propunem sa gestionam ambele categorii de studenti (buget, taxa), variantele ar putea
fi:
V1. Crearea a doua clase total diferite (StudentBuget si StudentTaxa) care sa gestioneze
cele doua categorii diferite de studenti.
Avantaj:
- Exista doua clase diferite care gestionează cele două entitați diferite (std taxa - std buget)
Dezavantaj:
- Duplicarea codului: 80-90 % din codul celor doua clase este identic
V2. Adaugarea la nivelul clasei Student de mai sus a tuturor informatiilor specifice (extra
Student), cumulate pentru ambele categorii de studenti, precum si un tip (membru in
clasa Student) care sa mentioneze tipul studentului: BUGET sau TAXĂ.
class StudentAny
{
typedef enum {
STD_BUGET, STD_TAXA } t_STDTYPE;
typedef enum {
STD_FR, STD_CAP, STD_SG, STD_SGMAJ } t_GRAD;
int m_Id;
char* m_Nume;
int m_Note[100];
t_STDTYPE m_Tip;
t_GRAD m_Grad;
int m_TaxeAchitate[20];
public:
StudentAny (int id, char *nume, int note[],
t_STDTYPE tip, t_GRAD grad, int taxe[]);
Avantaj:
- codul comun nu este duplicat
Dezavantaj:
- amestecam entitatile (compromis) la un moment dat devine complicat de lucrat
V3. Utilizarea mostenirii OOP (derivarea claselor): din clasa Student se vor deriva doua clase
Specializate: una pe std de la buget, cealalta pe std de la taxa.
class Student
{
int m_Id;
char *m_Nume;
int m_Note[100];
public:
Student (int id, char *nume, int note[]);
Student (const char *stdinfo);
typedef enum {
STD_FR,STD_CAP,STD_SG,STD_SGMAJ} t_GRAD;
public: public:
StudentBuget(int id, char *nume, StudentTaxa(int id, char *nume,
int note[], t_GRAD grad); int note[], int taxe[]);
StudentBuget(const char *stdinfo); StudentTaxa(const char *stdinfo);
void setGrad (t_GRAD grad) {/*...*/} void payTaxa (int val) {/*...*/}
t_GRAD getGrad () {/*...*/} int getSumaAchitata() {/*...*/}
//... //...
}; };
Observatii:
- O combinatie intre cele doua versiuni de mai sus: codul comun il avem o singura data si
avem doua clase diferite specifice pentru cele doua entitati diferite
- Desi, crestem numarul de clase in cadul programului, insa este mult mai eficient:
o nu duplicam codul - avantajul lui V2
o distingem clar entitatile (fiecare clasa specializata se ocupa de entitatea ei) –
avantajul lui V1
Mostenirea claselor:
- mostenirea claselor: derivarea claselor
- clasa din care se face mostenirea (derivarea) : clasă de bază, clasă părinte, super-clasă, etc.
- clasa mostenita (derivata): clasă copil, clasă derivată, sub-clasă, clasă specializată
- dintr-o clasă de bază se pot face una sau mai multe derivari
- dintr-o clasă derivată (clasă copil): se poate deriva mai departe un (sub)copil
(clasă nepot pentru clasa de bază)
void main ()
{
Student S ("101,Ionescu Vasile,8,9,5,10,8,9");
StudentBuget SB ("102,Popescu Ion,7,9,5,10,8,9,10,4");
StudentTaxa ST ("103,Vasilescu Bogdan,8,9,10,4");
S.print();
SB.print();
ST.print();
public:
StudentBuget (int id, char *nume, int note[], t_GRAD grad);
StudentBuget (const char *stdinfo);
void StudentBuget::print()
{
std::cout << "id: " << m_Id;
std::cout << "\nnume: " << m_Nume;
std::cout.precision (2);
std::cout << "\nmedie: " << std::fixed << this->getMedie() << std::endl;
std::cout << "grad: " << this->getGradStr();
}
const char* StudentBuget::getGradStr () const
{
switch (m_Grad) {
case STD_FR: return "std.fr.";
case STD_CAP: return "std.cap.";
case STD_SG: return "std.sg.";
case STD_SGMAJ: return "std.sg.maj";
default: return "std";
};
}
class B { /*...*/ };
class D : public B // public derivation
{ /*...*/ };
class B { /*...*/ };
class D : B // private derivation
{ /*...*/ };
class B { /*...*/ };
class D : private B // private derivation
{ /*...*/ };
Accesul (vizibilitatea) din clasa derivată la membrii mosteniti din clasa de bază:
Tip derivare Daca in clasa de bază un membru este: În clasa derivată el este/devine:
private inaccesibil
public protected protected
public public
private inaccesibil
private protected private
public public