Ce face class
O class descrie un tip de obiect: ce date conține și ce operații știe să facă. Din aceeași clasă poți crea oricâte obiecte, fiecare cu datele lui. Membrii unei clase sunt implicit private: din afară se ajunge la ei doar prin metodele public, ceea ce protejează datele de modificări greșite (încapsulare).
Constructorul are același nume ca și clasa și pregătește obiectul la creare; cel mai bine inițializează membrii în lista de inițializare (: sold_(suma)). Destructorul (~Nume()) rulează automat când obiectul dispare (la ieșirea din bloc) și eliberează resursele: fișiere, memorie, conexiuni. Această legătură între viața obiectului și resurse se numește RAII.
Singura diferență între class și struct este accesul implicit: private la class, public la struct. Prin convenție, class se folosește pentru obiecte cu reguli interne, struct pentru simple grupări de date.
Exemple
Exemplul 1: Un cont bancar cu reguli
sold_ este privat, deci nu poate fi modificat direct din main; orice retragere trece prin verificarea din metoda retrage.
#include <print>
#include <string>
#include <utility>
class Cont {
public:
Cont(std::string titular, double sold) : titular_(std::move(titular)), sold_(sold) {}
bool retrage(double suma) {
if (suma <= 0 || suma > sold_) {
return false;
}
sold_ -= suma;
return true;
}
void depune(double suma) { sold_ += suma; }
double sold() const { return sold_; }
const std::string& titular() const { return titular_; }
private:
std::string titular_;
double sold_;
};
int main() {
Cont cont("Ana Ionescu", 500);
cont.depune(200);
std::println("Retragere 1000: {}", cont.retrage(1000));
std::println("Retragere 300: {}", cont.retrage(300));
std::println("{} are {} lei", cont.titular(), cont.sold());
}
Rezultat
Retragere 1000: false
Retragere 300: true
Ana Ionescu are 400 lei
Exemplul 2: Constructor și destructor (RAII)
Destructorii rulează automat, în ordinea inversă creării, când obiectele ies din bloc. Nu trebuie apelați de mână.
#include <print>
#include <string>
#include <utility>
class Sesiune {
public:
explicit Sesiune(std::string utilizator) : utilizator_(std::move(utilizator)) {
std::println("Conectat: {}", utilizator_);
}
~Sesiune() {
std::println("Deconectat: {}", utilizator_);
}
private:
std::string utilizator_;
};
int main() {
Sesiune a("ana");
{
Sesiune b("mihai");
std::println("lucrez în bloc");
} // aici dispare b
std::println("înapoi în main");
} // aici dispare a
Rezultat
Conectat: ana
Conectat: mihai
lucrez în bloc
Deconectat: mihai
înapoi în main
Deconectat: ana
Exemplul 3: Mai mulți constructori și = delete
Constructorul fără parametri delegă la celălalt. = delete interzice copierea: o linie Fisier copie = f; nu s-ar compila.
#include <print>
#include <string>
#include <utility>
class Fisier {
public:
Fisier() : Fisier("fara_nume.txt") {}
explicit Fisier(std::string nume) : nume_(std::move(nume)) {}
Fisier(const Fisier&) = delete; // nu se poate copia
Fisier& operator=(const Fisier&) = delete;
const std::string& nume() const { return nume_; }
private:
std::string nume_;
};
int main() {
Fisier a;
Fisier b("raport.txt");
std::println("{} și {}", a.nume(), b.nume());
}
Rezultat
fara_nume.txt și raport.txt
Greșeli frecvente
- Uiți punctul și virgula după acolada de închidere a clasei:
class A { ... }fără;. Compilatorul dă erori ciudate pe linia următoare. - Inițializezi membrii prin atribuire în corpul constructorului, nu în lista de inițializare. Membrii
constși referințele nici nu pot fi inițializați altfel; în plus, membrii sunt inițializați în ordinea declarării în clasă, nu în ordinea din listă. - Gestionezi manual memorie (
newîn constructor,deleteîn destructor) și lași copierea implicită. Două obiecte vor șterge aceeași memorie. Foloseștestd::unique_ptr/std::vectorsau interzice copierea cu= delete.
Comenzi înrudite
struct: Grupează mai multe valori într-un singur tip; ca o clasă, dar cu membri publici implicit.public, private, protected: Specificatorii de acces: stabilesc cine poate folosi membrii unei clase și cum se moștenește o clasă de bază.this: Pointer către obiectul curent, disponibil în orice metodă nestatică a unei clase.virtual: Marchează o metodă care poate fi suprascrisă în clasele derivate; apelul printr-un pointer sau o referință la bază alege varianta tipului real.explicit: Interzice folosirea unui constructor sau a unui operator de conversie pentru conversii automate, ascunse.