Sari la conținut
EduCamp
Definitivat2020Teorie15 puncte✓ GRATUIT

Subiectul I, cerința 1

Încapsularea în programarea orientată pe obiecte

Principiul încapsulării, clase și obiecte, membrii unei clase, cele trei niveluri de acces, constructori și destructori, cu o problemă rezolvată printr-o clasă cu date alocate dinamic.

Principiul încapsulării

Încapsularea este unul dintre principiile fundamentale ale programării orientate pe obiecte. Ea constă în gruparea datelor și a metodelor care le prelucrează în aceeași clasă și în ascunderea datelor față de exterior.

Datele unui obiect nu pot fi citite sau modificate direct din afara clasei, ci numai prin metodele publice, care alcătuiesc interfața clasei.

În acest fel, reprezentarea internă a datelor poate fi schimbată fără rescrierea programelor care folosesc clasa, atât timp cât interfața rămâne aceeași. Verificările asupra valorilor se scriu o singură dată, în metodele clasei, și nu pot fi ocolite din exterior.

Clase și obiecte

Clasa este un tip de date definit de programator. Ea precizează ce date conține fiecare obiect de tipul ei și ce funcții se pot aplica asupra acestor date. Clasa este numai o descriere: prin declararea ei nu se rezervă memorie.

Obiectul este o variabilă de tipul dat de clasă și se mai numește instanță a clasei. Fiecare obiect are propriile valori pentru datele descrise în clasă. Legătura dintre clasă și obiect este aceeași cu cea dintre tipul int și o variabilă de tip int.

Membrii unei clase

Membrii unei clase sunt de două feluri:

  • datele membru, numite și câmpuri sau atribute — variabilele declarate în clasă, care dau starea obiectului;
  • funcțiile membru, numite și metode — funcțiile declarate în clasă, care lucrează cu datele obiectului.

Cele trei niveluri de acces

SpecificatorulDe unde se poate accesa membrul
privatenumai din funcțiile membru ale clasei și din funcțiile declarate prietene
protecteddin funcțiile membru ale clasei, din cele ale claselor derivate din ea și din funcțiile prietene
publicdin orice punct al programului în care obiectul este vizibil

Dacă nu se scrie niciun specificator, membrii unei clase declarate cu class sunt implicit private. Datele membru se declară private sau protected, iar funcțiile prin care se lucrează cu obiectul se declară public.

Constructori

Constructorul este o funcție membru specială, care poartă numele clasei și nu are tip de rezultat. Este apelat automat la crearea unui obiect și îi inițializează datele membru.

O clasă poate avea mai mulți constructori, deosebiți prin lista de parametri:

  • constructorul implicit, fără parametri;
  • constructori cu parametri, prin care datele obiectului primesc valori chiar la creare;
  • constructorul de copiere, care inițializează un obiect nou cu valorile altui obiect de același tip.

Dacă programatorul nu scrie niciun constructor, compilatorul generează un constructor implicit, care însă nu dă valori datelor membru.

Destructori

Destructorul este funcția membru apelată automat la distrugerea unui obiect, la încheierea execuției blocului în care a fost declarat sau când este eliberat cu delete. Poartă numele clasei precedat de caracterul ~, nu are parametri și nu are tip de rezultat. O clasă are cel mult un destructor.

Rolul lui este să elibereze resursele ocupate de obiect, în primul rând memoria alocată dinamic în constructor. Fără destructor, memoria alocată pentru fiecare obiect ar rămâne ocupată până la terminarea programului.

Problema propusă

Enunț. Se citesc de la tastatură un număr natural n (1 ≤ n ≤ 30) și, pentru fiecare dintre cei n elevi ai unei clase, numele elevului (un singur cuvânt, de cel mult 29 de litere), numărul k al notelor obținute la o disciplină (1 ≤ k ≤ 20) și notele însele. Numărul notelor diferă de la un elev la altul. Să se afișeze, pentru fiecare elev, media notelor sale, iar apoi numele elevului cu media cea mai mare.

Implementarea soluției.

#include <iostream>
#include <cstring>
using namespace std;

class Elev {
  private:
    char nume[30];
    int *note;      // alocat dinamic in constructor
    int nrNote;

  public:
    Elev(const char *n, int k, int v[]);
    ~Elev();
    float media();
    const char* numeleElevului();
};

/* Constructorul: copiaza numele, aloca memorie pentru exact atatea note
   cate are elevul si le copiaza in zona alocata. */
Elev::Elev(const char *n, int k, int v[]) {
    strcpy(nume, n);
    nrNote = k;
    note = new int[k];
    for (int i = 0; i < k; i++)
        note[i] = v[i];
}

/* Destructorul: elibereaza zona alocata in constructor. */
Elev::~Elev() {
    delete[] note;
}

float Elev::media() {
    int suma = 0;
    for (int i = 0; i < nrNote; i++)
        suma = suma + note[i];
    return (float)suma / nrNote;
}

const char* Elev::numeleElevului() {
    return nume;
}

int main() {
    int n;
    cin >> n;

    Elev *clasa[30];

    for (int i = 0; i < n; i++) {
        char nume[30];
        int k, v[20];

        cin >> nume >> k;
        for (int j = 0; j < k; j++)
            cin >> v[j];

        clasa[i] = new Elev(nume, k, v);
    }

    int celMaiBun = 0;
    for (int i = 0; i < n; i++) {
        cout << clasa[i]->numeleElevului() << " " << clasa[i]->media() << endl;
        if (clasa[i]->media() > clasa[celMaiBun]->media())
            celMaiBun = i;
    }

    cout << "Media cea mai mare: " << clasa[celMaiBun]->numeleElevului();

    for (int i = 0; i < n; i++)
        delete clasa[i];

    return 0;
}

Descrierea soluției. Clasa Elev grupează datele unui elev (numele, notele și numărul lor) și funcțiile care lucrează cu ele. Toate cele trei date membru sunt declarate private, deci nu pot fi citite sau modificate din afara clasei; ele pot fi accesate numai prin funcțiile declarate public.

Numărul notelor nu se cunoaște la scrierea programului și diferă de la un elev la altul, așa că vectorul notelor se alocă dinamic în constructor, cu exact atâtea elemente câte note are elevul, și se eliberează în destructor. Constructorul primește numele, numărul de note și notele și este apelat automat la crearea obiectului, prin operatorul new.

Media nu se păstrează ca dată membru, ci se calculează în funcția media de fiecare dată când este cerută, din notele obiectului. Restul programului nu are acces la vectorul de note și nu îl poate modifica, așa că media rezultă întotdeauna din notele memorate în obiect.

În programul principal, obiectele se creează cu new și se rețin într-un vector de pointeri, fiindcă fiecare obiect se poate crea numai după citirea datelor elevului, iar clasa nu are constructor fără parametri. La sfârșit fiecare obiect se eliberează cu delete, moment în care se apelează destructorul și se eliberează și vectorul de note.

Rezolvarea se poate citi pe educamp.ro, la adresa de mai sus.

Actualizat: 28 august 2026