+ All Categories
Home > Documents > Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Date post: 31-Dec-2016
Category:
Upload: duongdung
View: 247 times
Download: 0 times
Share this document with a friend
12
Programare orientata pe obiecte – limbajul C++/Java Laborator nr. 4 1 Exemplu 1: Laborator 4 I. Clase derivate. Mostenire. Notiuni introductive. II. Polimorfism Pornind de la clasa de baza patrulater, sa se implementeze clasa derivata paralelogram a acestei clase. #include<iostream.h> #include<conio.h> #include<math.h> class patrulater{ public: double xA,yA,xB,yB,xC,yC,xD,yD; int valid; patrulater(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4) { xA=x1;yA=y1; xB=x2;yB=y2; xC=x3;yC=y3; xD=x4;yD=y4; valid_1(); } double valid_1() { if(((xA!=xB)||(yA!=yB))&&((xA!=xC)||(yA!=yC))&& ((xA!=xD)||(yA!=yD))&&((xB!=xC)||(yB!=yC))&&((xB!=xD)|| (yB!=yD)) && ((xC!=xD)||(yC!=yD))) valid =1; else valid=0; return valid; } void afis_1() { if (valid) cout<<"Figura este patrulater."; else cout<<"Figura nu este patrulater."; } }; class paralelogram:public patrulater{ public: double l1,l2,l3,l4,l5; int validp; int valid_2() { valid_1(); if (valid) { l5=(xA-xB)*(xA-xB)+(yA-yB)*(yA-yB);
Transcript
Page 1: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

1

Exemplu 1:

Laborator 4

I. Clase derivate. Mostenire. Notiuni introductive.

II. Polimorfism

Pornind de la clasa de baza patrulater, sa se implementeze clasa

derivata paralelogram a acestei clase.

#include<iostream.h>

#include<conio.h>

#include<math.h>

class patrulater{

public:

double xA,yA,xB,yB,xC,yC,xD,yD;

int valid;

patrulater(double x1,double y1,double x2,double y2,double x3,double y3,double

x4,double y4)

{

xA=x1;yA=y1;

xB=x2;yB=y2;

xC=x3;yC=y3;

xD=x4;yD=y4;

valid_1();

}

double valid_1()

{

if(((xA!=xB)||(yA!=yB))&&((xA!=xC)||(yA!=yC))&&

((xA!=xD)||(yA!=yD))&&((xB!=xC)||(yB!=yC))&&((xB!=xD)|| (yB!=yD)) && ((xC!=xD)||(yC!=yD)))

valid =1;

else

valid=0;

return valid;

}

void afis_1()

{

if (valid)

cout<<"Figura este patrulater.";

else

cout<<"Figura nu este patrulater.";

}

};

class paralelogram:public patrulater{

public:

double l1,l2,l3,l4,l5;

int validp;

int valid_2()

{

valid_1();

if (valid)

{

l5=(xA-xB)*(xA-xB)+(yA-yB)*(yA-yB);

Page 2: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

2

l1=sqrt(abs(l5));

l2=sqrt(abs((((xC-xB)*(xC-xB))+((yC-yB)*(yC-yB)))));

l3=sqrt(abs((((xC-xD)*(xC-xD))+((yC-yD)*(yC-yD)))));

l4=sqrt(abs((((xA-xD)*(xA-xD))+((yA-yD)*(yA-yD)))));

if ((l1==l3)&&(l2==l4))

{ validp=1; }

else

{ validp=0; }

}

else

validp=0;

return validp;

}

void afis_2()

{

if (validp)

cout<<"\nFigura este paralelogram.";

else

cout<<"\nFigura nu este paralelogram.";

}

paralelogram(double x1, double y1, double x2, double y2, double x3, double y3,

double x4, double y4): patrulater(x1,y1,x2,y2,x3,y3,x4,y4)

{ valid_2(); }

};

void main()

{

paralelogram pp(0.0,0.0,1.0,0.0,1.0,1.0,0.0,1.0);

clrscr();

cout<<"Dati cordonatele varfurilor.";

cout<<"\n xA=";cin>>pp.xA; cout<<" yA=";cin>>pp.yA;

cout<<"\n xB=";cin>>pp.xB; cout<<" yB=";cin>>pp.yB;

cout<<"\n xC=";cin>>pp.xC; cout<<" yC=";cin>>pp.yC;

cout<<"\n xD=";cin>>pp.xD; cout<<" yD=";cin>>pp.yD;

pp.valid_1();

pp.afis_1();

getch();

pp.valid_2();

pp.afis_2();

getch();

}

Dupa executia programului se va afisa:

Page 3: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

3

Exemplu 2: Exemplu de redefinire a unei functii care nu apeleaza functia

corespunzatoare din clasa de baza. Cele doua clase NumarComplex,

clasa de baza si NumarReal, clasa derivata au definite cate o functie

membru afisare(). In clasa derivata este redefinita fara a apela varianta din

clasa de baza.

#include <iostream.h>

#include <conio.h>

//clasa de baza NumarComplex

class NumarComplex{

protected:

double re,im;

public:

NumarComplex(double, double);

void afisare();

};

NumarComplex::NumarComplex(double RE, double IM)

{

re = RE;

im = IM;

}

void NumarComplex::afisare()

{

cout<<"\n Numarul complex este : "<<re<<"+"<<im<<"*i";

}

// clasa Numar Real derivata din clasa NumarComplex

class NumarReal:public NumarComplex{

public:

NumarReal(double RR):NumarComplex(RR,0.0) { }

void afisare();

};

void NumarReal::afisare()

{

cout<<"\n Numarul real este : "<<re;

}

void main()

{

NumarReal r = NumarReal(15);

NumarComplex z = NumarComplex(-1,3);

clrscr();

r.afisare();

z.afisare();

}

Dupa executia programului se va afisa:

Page 4: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

4

Exemplu 3: Sa se defineasca o clasa sir care sa se utilizeze la instantierea

sirurilor de caractere.

Sa se scrie un program care realizeaza urmatoarele operatii asupra

obiectelor de tip sir:

initializare

citire de siruri de caractere de la tastatura

copiere de obiecte de tip sir

atribuiri de obiecte de tip sir

afisari de siruri de caractere din compunerea obiectelor de tip sir.

Solutie:

#include <iostream.h>

#include <stdio.h>

#include <string.h>

//enum Boolean {false,true}; //EROARE de compilare pe MinGW

class sir

{

// date membru protejate(private)

// pointer catre zona de memorie in care se pastreaza caracterele sirului

char *psir;

int lung; //lungimea sirului(numarul de caractere)

// functii membru neprotejate

public:

// constructor pt. intializarea obiectului cu pointerul

// spre sirul de caractere; acesta se pastreaza in memoria heap

sir(char *s);

//constructor care rezerva zona de memorie in memoria heap si pastreaza sirul vid

sir(int nrcar=70);

//constructor de copiere

sir(const sir&);

//destructor

~sir();

//returneaza lungimea sirului

int retlung();

//afiseaza sirul de caractere

void afsir();

//citeste un sir de caractere

int citsir();

// transfera sirul spre care pointeaza s in zona rezervata pentru sirul obiectului

// curent

// daca nu exista zona suficienta, se truncheaza sirul spre care pointeaza s si se

// returneaza valoarea false; in caz contrar se returneaza true

bool atribsir(sir *s);

};

sir::sir(char *s)

{

lung=strlen(s);

psir=new char[lung+1];

strcpy(psir,s);

}

sir::sir(int dim)

{

lung=dim;

psir=new char[lung+1];

Page 5: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

5

*psir='\0';

}

sir::sir(const sir& s)

{

lung=s.lung;

psir=new char[lung+1];

strcpy(psir,s.psir);

}

sir::~sir()

{

delete psir;

}

int sir::retlung()

{

return lung;

}

void sir::afsir()

{

cout<<psir<<endl;

}

// citeste un sir de caractere de la tastatura si-l pastreaza in zona heap rezervata

// pentru obiectul curent

// returneaza 0 la sfarsit de fisier, -1 la trunchierea sirului citit, 1, altfel

int sir::citsir()

{

char temp[255];

if(gets(temp)==0) return 0;

strncpy(psir,temp,lung);

*(psir+lung)='\0';

if(strlen(temp) > lung ) return 1;

else return 1;

}

bool sir::atribsir(sir* s)

{

strncpy(psir,s->psir,lung);

if(strlen(s->psir) > lung ) return false;

else return true;

}

int main(void)

{

sir sir1=("Limbajul C++ este un C mai bun");

sir sir2=("Limbajul C++ suporta stilul de programare:\n\

- prin abstractizarea datelor;\n\

- orientata spre obiecte");

sir sir3; // instantiere fara initializare; sir3 contine sirul vid

sir sir4=sir1; //instantiere folosind constructorul de copiere

//afisarea obiectelor instantiate

cout<<"sir1 : ";sir1.afsir();

cout<<"sir2 : ";sir2.afsir();

cout<<"sir3 : ";sir3.afsir();

cout<<"sir4 : ";sir4.afsir();

//atribuiri de siruri

cout<<"========== Trunchieri ==========="<<endl;

if(sir3.atribsir(&sir1) == false) cout<<"trunchiere la atribuire"<<endl;

Page 6: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

6

Exemplu 4:

sir3.afsir();

if(sir3.atribsir(&sir2) == false) cout<<"trunchiere la atribuire"<<endl;

sir3.afsir();

}

Sa se definesca o clasa punct care sa se utilizeze la instantierea

punctelor din plan prin coordonate (abcisa si ordonata).

Sa se scrie un program care genereaza obiecte de tip punct ale

caror coordinate se genereaza aleator. Programul afiseza punctele care apartin ecranului, iar in

final se indica:

numarul m al punctelor afisate

numarul n al punctelor generate

raportul m/n

Observatie: Punctele care apartin ecranului se incadreaza in dimensiunile acestuia : 80 coloane si

25 de linii.

Solutie: #include <iostream.h>

#include <conio.h>

#include <stdlib.h>

class punct

{

// date membru protejate(private)

double x; //abcisa

double y; //ordonata

// functii membru neprotejate

public:

punct(double abs=0, double ord=0);

punct(const punct&);

//citeste coord. punctului

void citpunct();

//afiseaza coordonatele punctului

void afispunct();

//translatie pe directia abcisei

void xtrans(double dx);

//translatie pe directia ordonatei

void ytrans(double dy);

//returneaza abcisa

double retx();

//returneaza ordonata

double rety();

};

// constructor pentru instantierea obiectelor de tip punct; implict se instantiaza

// originea axelor

punct::punct(double abs,double ord)

{ x=abs; y=ord; }

punct::punct(const punct& p)

{ x=p.x; y=p.y; }

void punct::citpunct() // citeste coord. punctului

{

cout<<"Dati abcisa "; cin>>x;

cout<<"Dati cordonata "; cin>>y;

}

Page 7: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

7

void punct::afispunct() // afiseaza coordonatele punctului

{ cout<<" ("<<x<<","<<y<<") "; }

void punct::xtrans(double dx) //translatie pe directia abcisei

{ x+=dx; }

void punct::ytrans(double dy) //translatie pe directia ordonatei

{ y+=dy; }

double punct::retx() //returneaza abcisa

{ return x; }

double punct::rety() //returneaza ordonata

{ return y; }

void main(void)

{

int m=0,n=0;

clrscr();

cout<<endl<<"Incepe generarea numerelor "<<endl;

for(;;)

{

double xaleator=rand()%100;

double yaleator=rand()%100;

punct pct(xaleator,yaleator);

n++;

if(xaleator>0 && xaleator<=80 && yaleator>0 &&yaleator<=25)

//afiseaza punctul

{

m++;

pct.afispunct();

if(m%22==0)

{

cout<<endl<<"Apasati o tasta pentru a continua ";

cout<<endl<<"Apasati zero pentru a termina "<<endl;

if(getch()=='0') break;

}

}

}

cout<<"Numarul punctelor afisate "<<m<<endl;

cout<<"Numarul punctelor generate "<<n<<endl;

cout<<"Raportul m/n "<<(double)m/n<<endl;

getch();

}

Page 8: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

8

Probleme propuse:

1. Pornind de la clasa de baza paralelogram, sa se implementeze clasa

derivata dreptunghi.

2. Pornind de la clasa de baza dreptunghi, sa se implementeze clasa

derivata patrat.

3. La problema nr. 1 sa se adauge o functie arie() pentru clasa derivata

dreptunghi.

4. La problema nr. 2 sa se adauge o functie arie() pentru clasa derivata

patrat.

5. Pornind de la clasa de baza punct, sa se implementeze clasa derivata

triunghi.

6. La problema nr. 5 sa se adauge o functie arie()pentru clasa derivata

triunghi.

Page 9: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

9

II. Polimorfism

La cursul de Proiectarea algorimilor am invatat despre metoda backtracking

standardizat. Am observat acolo ca metoda in sine consta dintr-o unica secventa de

instructiuni care apela diferite functii care aveau intotdeauna acelasi nume, dar care se

modificau de la un program la altul.

Vom incerca acum, sa construim o clasa in care functiile init(), am_succesor() si

celelalte sa fie definite initial cu valori simple, iar apoi in clasele derivate sa poata fi

redefinite astfel incat sa rezolve fiecare problema in parte.

Dificultatea consta in faptul ca functia run() care contine algoritmul de

backtracktring va apela functiile init(), succesor(), s.a.m.d. si deci obiectul care o

foloseste trebuie sa contina si aceste functii. De aceea ele vor fi definite din start – in

clasa de baza – ca fiind virtuale, pentru ca apoi in clasele derivate sa poata fi redefinite

corespunzator fiecarei clase in parte care rezolva un anumit tip de problema. Deci, vom

aplica polimorfismul.

Initial in fisierul cu numele ‘back.cpp’, vom declara clasa bkt, in care functiile

init(), am_succesor(), e_valid(), solutie() si tipar() vor fi declarate virtuale. Deoarece

ele nu vor fi niciodata apelate in cadrul acestei clase, vor avea ‘corpul’ vid. De asemenea,

variabilele n, k, as, ev se gasesc in orice program backtracking si deci, vor fi declarate

aici.

Fisierul ‘back.cpp’ contine clasa bkt :

class bkt{

public:

int st[10],n,k;

virtual void init() {}

virtual int am_succesor() { return 0; }

virtual int e_valid() { return 0; }

virtual int solutie() { return 0; }

virtual void tipar() {}

void bkt::run();

};

void bkt::run()

{

int as;

k=1;init();

while(k>0)

{

do{

}while( (as=am_succesor()) && !e_valid() );

if(as)

if(solutie()) tipar();

else

{ k++; init(); }

else k--;

Page 10: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

10

Exemplu 1:

}

}

Exemple de probleme care pot si rezolvate acum prin utilizarea clasei bkt, prin

polimorfism:

Generarea permutarilor

Se cere sa se genereze toate permutarile multimii {1,2,…,n}.

Pentru a folosi clasa bkt vom defini o alta clasa, care o

mosteneste pe aceasta si care va avea functiile clasei initiale dar redefinite. Vom folosi un

constructor care va avea rolul de a citi valoarea lui n.

Fisierul ‘perm.cpp’ va defini clasa permut care va fi derivata din clasa bkt:

#include<iostream.h>

#include "back.cpp"

class permut:public bkt{

public:

permut (int v) { n=v; }

virtual void init();

virtual int am_succesor();

virtual int e_valid();

virtual int solutie();

virtual void tipar();

};

void permut::init()

{ st[k]=0; }

int permut::am_succesor()

{

if(st[k]<n){ st[k]++; return 1; }

else return 0;

}

int permut::e_valid()

{

for(int i=1;i<k;i++)

if(st[i]==st[k]) return 0;

return 1;

}

int permut::solutie()

{ return (k==n); }

void permut::tipar()

{

for(int i=1;i<=k;i++)

cout<<st[i]<<" ";

cout<<endl;

}

Se observa ca acest fisier – la fel ca si cel anterior – nu are functie main(),

deoarece poate fi folosit in orice alt program care rezolva probleme de generarea

permutarilor. Si anume poate fi folosit in urmatorul fiser care afiseaza rezultatul generarii

permutarilor multimii {1,2,…,n} :

Page 11: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

11

Exemplu 2:

#include<iostream.h>

#include "perm.cpp"

int main()

{

permut x(3);

x.run();

}

Problema celor n regine(dame)

Se cere sa se genereze toate posibilitatile de asezare a n

dame pe o tabla de sah de dimensiune n*n, astfel in cat sa nu se

‘atace’ reciproc.

Dupa cum stim, rezolvarea problemei difera de generarea permutarilor doar

printr-o singura metoda : e_valid(). Atunci, vom redefini aceasta metoda din clasa

permut, pentru a putea obtine solutia dorita :

Fisierul ‘regine.cpp’ va contine clasa dame care va fi derivata din clasa permut :

#include<math.h>

#include "perm.cpp"

class dame : public permut{

public:

dame(int v) : permut(v) {};

virtual int dame::e_valid();

};

int dame::e_valid()

{

for(int i=1;i<k;i++)

if( (st[i]==st[k]) || abs(st[k]-st[i])==abs(k-i) ) return 0;

return 1;

}

Iar acum pentru scrierea programului care rezolva problema celor n regine vom

construi fisierul ‘dame.cpp’ in care vom include fisierul ‘regine.cpp’ :

Codul sursa al programului este:

#include<iostream.h>

#include "regine.cpp"

int main()

{

dame x(8);

x.run();

}

Page 12: Exemplu 1: I. Clase derivate. Mostenire. Notiuni introductive. II ...

Programare orientata pe obiecte – limbajul C++/Java

Laborator nr. 4

12

Probleme propuse spre rezolvare:

1. Pornind de la clasa de baza bkt (din fisierul “back.cpp”), sa se implementeze, prin

polimorfism clasa virtuala ture pentru a rezolva problema turelor: Se cere sa se genereze

toate posibilitatile de asezare a n ture pe o tabla de sah de dimensiune n*n, astfel in cat sa

nu se ‘”atace” reciproc.

2. Pornind de la clasa de baza bkt (din fisierul “back.cpp”), si clasa derivata permut (din

fisierul “perm.cpp”), sa se implementeze, prin polimorfism clasa virtuala cuvinte pentru

a rezolva urmatoarea problema: Se da o multime alcatuita din n litere distincte. Se cer

toate cuvintele care se pot forma cu ele, astfel incat fiecare cuvant sa contina n litere

distincte.

Exemplu: Daca avem multimea {a,b,c}, atunci vom avea cuvintele: abc, acb, bac, bca,

cab, cba.

3. Pornind de la clasa de baza bkt (din fisierul “back.cpp”), sa se implementeze, prin

polimorfism clasa virtuala numere pentru a rezolva urmatoarea problema: Sa se afiseze

toate numerele naturale de n cifre care contin p cifre de 1.

Exemplu: Pentru n=3 si p=2 se obtin solutiile: 101, 110, 112, 113, ... , 119, 121, 131, 141,

... .

4. Pornind de la clasa de baza bkt (din fisierul “back.cpp”), si clasa derivata permut (din

fisierul “perm.cpp”), sa se implementeze, prin polimorfism clasa virtuala numar pentru

a rezolva urmatoarea problema: Sa se descompuna un numar natural in toate modurile

posibile, ca suma de p numere naturale nenule, distincte. Solutiile care difera doar prin

ordinea termenilor nu se vor considera disctincte. Exemplu: Pentru n=10 si p=3 se obtin

solutiile: (1, 2, 7), (1, 3, 6), (1, 4,5), (2, 3, 5).


Recommended