Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-is:laboratoare:03 [2020/09/09 12:21]
alexandru.ionita99 [2. Structura de fișiere a unei aplicații]
— (current)
Line 1: Line 1:
-===== Laboratorul 03: Definirea și utilizarea claselor. Funcții constructor ===== 
- 
-**__Introducere__\\ 
- 
-__Resurse__** 
- 
-==== 1. Introducere în programarea obiectuală ==== 
- 
-=== 1.1. Abordarea orientată pe obiecte === 
- 
-Asa cum am observat in curs, evolutia limbajelor de programare a condus la cresterea gradului de abstractizare,​ ceea ce inseamna ca un program se distanteaza din ce in ce mai mult de limitarile impuse de masina pe care ruleaza acesta.\\ 
-Abordarea orientata pe obiecte reprezinta cea mai flexibila si puternica abstractizare de limbaj de pana acum, ce ne permite sa descriem o solutie in termenii problemei, mai repede decat in cei ai masinii pe care solutia ruleaza.\\ 
-In cadrul programarii obiectuale, structurile de date sunt imbinate cu algoritmi necesari prelucrarii datelor, rezultand tipuri de date complexe, cu numele de **clase**, rezultand o abordare pragmatica si naturala a problemei ce trebuie rezolvata de catre programator.\\ 
- 
-<note tip>​**Avantaje ale utilizarii POO:** 
-  * Protejarea datelor prin incapsulare 
-  * Modularizare sporita a aplicatiei 
-  * Usurinta in impartirea sarcinilor in echipa 
-  * Suport pentru extinderea usoara a aplicatiei (mostenire, polimorfism) ​ 
-</​note>​ 
- 
- 
- 
-=== 1.2. Clase === 
-Clasa reprezinta un tip de date definit de utilizator, astfel incat sa il ajute in rezolvarea problemei care ii este data. \\ 
-O clasa contine:\\ 
-  * un **nume** propriu 
-  * un set de **atribute** (date) 
-  * un set de comportamente/​functionatiltati - functii membre/​**metode** 
- 
-Putem gandi o clasa ca pe o matrita pe care o utilizam in **instantierea** / **crearea** de obiecte similare, deci care au aceleasi atribute.\\ 
-De exemplu, in lume exista sute de producatori de masini, fiecare cu propriile modele. Cu toate ca modelele difera intre ele, ne putem gandi la atribute comune tuturor masinilor (numele producatorului,​ modelul, numarul de locuri, culoarea etc), dar si la metode comune (afisare, modificare, getCuloare, getNr_locuri etc).\\ 
-Astfel, putem pune la un loc aceste atribute pentru a crea clasa **Masina**. Aceasta clasa va fi  **instantiata**,​ pentru a crea **obiecte** cu date proprii:\\ 
- 
-<code cpp> 
-class Masina 
-{ 
-  private: //implicit private, daca nu specificam ​ 
-   ​string producator; 
-   ​string model; 
-   ​string culoare; 
-   int nr_locuri; 
-    
-  public: 
-   void afisare(void) const; 
-   void modificare(const string&,​ const string&,​ string&,​ int); 
-   ​string&​ getCuloare(void) const; 
-   int getNr_locuri(void) const; 
-}; 
-</​code>​ 
- 
-<note warning>​**Structura vs Clasa: **\\  
-  * **asemanare fundamentala:​** ambele pot contine atat date, cat si functii 
-  * **diferenta fundamentala:​** membrii claselor sunt **implicit private**, spre deosebire de structuri, unde acestia sunt **implicit public** 
-</​note>​ 
- 
-<note warning>​Cuvintele cheie (modificatori de acces) ce modifica "​vizibilitatea"​ membrilor:​\\ 
-  * **private** - date vizibile doar in clasa din care fac parte 
-  * **public** - date vizibile de oriunde 
-</​note>​ 
- 
-<note important>​Obiectele reprezinta instante ale unei clase, in cadrul carora atributele au valori, iar metodele pot fi folosite. </​note>​ 
- 
-=== 1.3. Functiile membre (metode) ale unei clase === 
-Metodele reprezinta proceduri ce sunt asociate claselor si obiectelor. Aceste pot accesa atributele si pot apela alte functii membre ale unei clase (inclusiv pe cele declarare **private**).\\ 
-Un exemplu de implementare a unei metode:\\ 
-<code cpp> 
-void Masina::​modificare(const string& prod, const string& mod, const string& cul, int locuri){ 
-producator = prod; //referiri la atributele clasei 
-model = mod; 
-culoare = cul; 
-nr_locuri = locuri; 
-} 
-</​code>​ 
- 
-<note important>​Pentru a implementa functiile membre sunt necesare referiri la atributele clasei, nu la un obiect anume</​note>​ 
- 
- 
-Apelarea functiilor se face folosind operatorii de selectie **.** / **->**. La apelare, functia este informata asupra identitatii obiectului asupra caruia va actiona prin transferul unui parametru implicit - **referinta** la obiectul care face apelul:\\ 
-<code cpp> 
-Masina m; //​instantierea unui obiect de tipul Masina 
-m.modificare("​Dacia",​ "​Logan",​ "​rosu",​ 5) 
-// SAU 
-Masina *m = new Masina(); //​instantierea,​ de aceasta data sub forma de pointer 
-m->​modificare("​Dacia",​ "​Logan",​ "​rosu",​ 5) 
-</​code>​ 
-<note important>​La apelul functiei, este testata declararea acesteia in clasa Masina (acelasi nume si aceeasi semnatura), dar si daca este implementata. Daca da, se apeleaza functia si i se transmite referita catre m (adresa lui m)</​note>​ 
- 
-<note tip>​Metodele pot fi: \\ 
-  * declarate inline 
-  * supradefinite 
-  * declarate public (in general), dar pot fi si private 
-</​note>​ 
- 
- 
- 
-=== 1.4. Constructori === 
-Constructorii reprezinta **metode speciale**, membre ale clasei, ce prezinta urmatoarele proprietati:​ 
-  * sunt apelati in momentul crearii obiectelor 
-  * au acelasi nume ca si clasa 
-  * **NU** au un tip de date returnat 
-  * se pot supradefini 
- 
-<note warning>​Conform standardului C98, constructorul fara parametri si cel de copiere sunt generati automat de catre compilator, **doar in lipsa implementarii efective a unui constructor**</​note>​ 
- 
-<note tip>​Tipurile de constructori sunt: 
-  * Constructori fara parametri 
-  * Constructori cu parametri 
-  * Constructori de copiere 
- 
-</​note>​ 
- 
-=== 1.5. Destructori === 
-Destructorii reprezinta un alt tip de **metode speciale**, fara tip sau parametri, cu rolul de a elibera spatiul de memorie ocupat de un obiect. Formatul lor este //​~nume_clasa()//​\\ 
-Destructorul se apeleaza explicit doar in contextul pointerilor,​ altfel se apeleaza automat cand o variabila elibereaza spatiul de memorie (la finalul duratei sale de viata)\\ 
-<note warning>​Compilatorul genereaza automat un destructor in lipsa implementarii de catre utilizator. Totusi, pentru clase ce contin atribute **pointer**,​ destructorul **trebuie** implementat,​ pentru a asigura o eliberare corecta a memoriei </​note>​ 
- 
-=== 1.6. Exemplu === 
-In continuare, vom prezenta un exemplu de implementare al constructorilor si destructorului pentru o clasa:\\ 
-<code cpp> 
-class Dreptunghi 
-{ 
- ​private:​ 
-  int lungime; 
-  int latime; 
- 
- ​public:​ 
-  Dreptunghi();​ //​Constructor fara parametri, generat default daca nu este definit 
-  Dreptunghi(int,​ int = 0); //​Constructor cu parametri. Daca este implementat,​ cel fara parametri nu mai este generat default 
-  Dreptunghi(const Dreptunghi&​);​ //​Constructor de copiere, generat default daca nu este definit 
-  ~Dreptunghi();​ //​Destructor. Este generat default si nu este necesar in acest context, deoarece nu avem tipuri de date pointer (*). Doar pentru exemplificare 
-}; 
- 
-///​Implmementare metode/// 
- 
-Dreptunghi::​Dreptunghi() 
-{ 
-    lungime = 0; 
-    latime = 0; 
-} 
- 
-Dreptunghi::​Dreptunghi(int lungime, int latime) 
-{ 
-    this->​lungime = lungime; 
-    this->​latime = latime; 
-} 
- 
-Dreptunghi::​Dreptunghi(const Dreptunghi&​ d) 
-{ 
-    this->​lungime = d.lungime; 
-    this->​latime = d.latime; 
-} 
- 
-Dreptunghi::​~Dreptunghi() 
-{ 
-    //Nu trebuie eliberat manual spatiul de memorie. Eventual, putem seta parametrii egali cu 0: 
-    this->​lungime = 0; 
-    this->​latime = 0; 
-} 
- 
-</​code>​ 
- 
-<note tip>​Puteti rula [[https://​repl.it/​@alexionita99/​Lab3exempleconstructoridestructori|aici]] exemplul de mai sus pentru a observa diferite modalitati de intializare ale obiectelor. Observati utilizarea a 3 fisiere in cadrul acestui exemplu. Despre acest tip de implementare vom vorbi in partea a doua a laboratorului </​note>​ 
- 
-<note important>​O initializare de tipul **Dreptunghi *g = new Dreptunghi[2]{{10,​ 20},{20, 30}}** se numeste **List initialization** si reprezinta o modalitate de apelare a constructorilor **cu parametri** pentru elementele unui vector, spre deosebire de **Dreptunghi *g = new Dreptunghi[2]**,​ cand este apelat de 2 ori constructorul fara parametri. Puteti afla [[https://​en.cppreference.com/​w/​cpp/​language/​list_initialization|aici]] mai multe detalii ​ 
-</​note>​ 
- 
-==== 2. Structura de fișiere a unei aplicații ==== 
-Structura de fisiere a unei aplicatii CPP cu clase este: 
- 
-  * nume.h - **fisier header** care contine **definitia clasei** (sau a unui grup de clase inrudite) 
-  * nume.cpp - **fisier sursa** care contine **implementarea clasei/​claselor** - concret e vorba de **functiile membre** care nu au fost definite chiar in definitia clasei 
-  * altnume.cpp - program principal (de exemplu un program de test) 
- 
-<note warning>​Impartirea in fisiere header si sursa nu este obligatorie,​ dar este indicata pentru usurinta in citirea codului. </​note>​ 
- 
-In continuare, vom prezenta un exemplu de aplicatie ce respecta structura de fisiere mentionata anterior. Aplicatia poate fi **rulata si descarcata** [[https://​repl.it/​@alexionita99/​lab3stack|aici]]:​ 
- 
-Fisierul **stack.h** contine definitia clasei: 
-<code cpp> 
-class stack { 
-int *buf; 
-int sp; // Acesti membri sunt impliciti private. 
-int nrmax; // Ei pot fi accesati doar prin functii (metode) 
-char nume[10]; // ale clasei 
- 
- 
-public: 
-// 
-// Aceasta este o functie constructor. 
-// Ea are acelasi nume cu clasa si este fara tip (nici macar void). 
-// Functia constructor este apelata la crearea obiectelor (statica, auto sau dinamica). 
-// 
-stack (const char *); 
-stack (int, const char *); // Alt constructor care va fi definit in exterior 
- 
-~stack(); // Destructor: functie care va fi apelata la incetarea 
-// duratei de viata a obiectului 
- 
-int is_empty() { return sp == -1; }     // Functii implementate in  
-int is_full() { return sp == nrmax-1; } // definitia clasei 
-void push (int); 
-int pop(); 
-char *getnume() { return (char *) nume; } 
-}; 
- 
-</​code>​ 
- 
-Membrii **private** ai clasei **stack** sunt: 
-  * buf: pointer la un tablou de intregi 
-  * sp: indicatorul de stiva (initializat cu -1 <==> stiva vida) 
-  * nrmax: dimensiunea bufferului 
-  * nume: un nume asociat obiectului 
- 
- 
-Exista doi **constructori**,​ unul cu parametru unic (numele clasei) si al doilea cu 2 parametri (dimensiune buffer si numele obiectului). Faptul ca pot exista mai multe functii constructor este o consecinta directa a **supradefinirii**. 
- 
-**Metodele** sunt: is_empty, is_full, push, pop, getnume, cu semnificatiile evidente.\\ \\ 
- 
-Fisierul **stack.cpp** contine implementarile metodelor clasei (doar cele care nu au fost implementate in definitie): 
- 
-<code cpp> 
-#include <​iostream>​ 
-#include <​cstdlib>​ 
-using namespace std; 
-#include <​string.h>​ 
-#include "​stack.h"​ //header-ul este inclus in fisierul sursa 
- 
-stack::​stack(const char *obnume) 
-{ 
-  buf = new int [100]; ​ 
-  sp = -1; nrmax = 100; 
-  strncpy(nume,​ obnume, 9); 
-  cout<<"​Constructor cu dimensiune implicita pentru obiectul "<<​nume<<"​\n";​ 
-} 
- 
-stack::​stack(int dim, const char *obnume) 
-{ 
-  // Constructor cu dimensiune precizata 
-  buf = new int [nrmax = dim]; 
-  sp = -1; 
-  strncpy(nume,​ obnume, 9); 
- 
-  cout << "​Constructor cu dimensiune explicita = " << dim << " pentru obiectul " << nume << "​\n";​ 
-} 
- 
-stack::​~stack() 
-{ 
-  delete [] buf; 
-  cout << "​Destructor pentru obiectul " << nume << "​\n";​ 
-} 
- 
-void stack::​push(int elem) 
-{ 
-  if (!is_full()) 
-    buf[++sp] = elem; 
- 
-  else { 
-    cout << "​Eroare:​ stiva plina\n";​ 
-    exit(1); 
-  } 
-} 
- 
-int stack::​pop() 
-{ 
-  if (!is_empty()) 
-    return buf[sp--]; 
- 
-  else { 
-    cout << "​Eroare:​ stiva vida\n";​ 
-    exit(1); 
-    return -1; // Doar ca sa se respecte tipul functiei 
-  } 
-} 
- 
-</​code>​ 
- 
-Pentru a pune in evidenta secventa de creare/​distrugere a obiectelor, in functiile constructor si destructor s-au prevazut mesaje adecvate. De observat utilizarea **operatorului de rezolutie ::**, care precizeaza ca functiile respective sunt membre ale clasei **stack** (am putea avea o alta functie is_full care sa fie membra a unei clase coada). \\ \\ 
- 
-Fisierul **main.cpp** reprezinta programul principal (de test) 
- 
-<code cpp> 
-#include <​iostream>​ 
-#include <​cstdlib>​ 
-using namespace std; 
-#include "​stack.h"​ // Fisier header stack 
- 
-stack a("​a"​);​ //variabila globala 
- 
-int main(int argc, char *argv[]) 
-{ 
-int i; 
-stack b("​b"​);​ 
-cout << "​\n\n"​ << "Start main\n";​ 
- 
-stack c(200, "​c"​);​ 
-stack *pd = new stack(300, "​d"​);​ 
- 
-a.push(1); 
-a.push(2); 
-pd->​push(3);​ 
-cout << "Pop din stiva " << pd->​getnume() << ": " << pd->​pop() << "​\n";​ 
- 
-// 
-// Etc., etc. 
-// 
-delete pd; // A fost alocat dinamic, deci eliberam memoria 
-cout << "​Sfarsit main\n";​ 
- 
-system("​PAUSE"​);​ 
-return EXIT_SUCCESS;​ 
-} 
- 
-</​code>​ 
- 
-Se defineste un obiect stack la nivel exterior **"​a"​** (cu alocare statica). El va fi creat inainte de a incepe executia functiei **main**. In **main** se definesc doua obiecte in clasa auto (**"​b"​ si "​c"​**) si unul prin alocare dinamica (a se vedea forma **new stack(...)**). Apoi se fac cateva operatii uzuale cu stivele astfel definite. La consola se va urmari si explica secventa de mesaje din functiile constructor,​ destructor si 
-main. De observat afisarea comoda la consola (cout) cu operatorul << (e necesar #include <​iostream.h>​). 
- 
  
poo-is/laboratoare/03.1599643300.txt.gz · Last modified: 2020/09/09 12:21 by alexandru.ionita99
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0