friend în C++

Dă unei funcții sau altei clase acces la membrii privați și protejați ai clasei.

Sintaxă
class A {
    friend void functie(const A&);   // funcție prietenă
    friend class B;                  // clasă prietenă
};

Ce face friend

Membrii private sunt accesibili doar metodelor clasei. Uneori o funcție din afara clasei are nevoie de ei: cel mai des operatorul de afișare operator<<, care trebuie să fie funcție liberă (în stânga are fluxul, nu obiectul). Declarând-o friend în clasă, îi dai acces.

Prietenia este dată de clasă, nu cerută: doar clasa poate spune cine îi este prieten. Nu se moștenește și nu este reciprocă (dacă A este prietena lui B, B nu devine automat prietena lui A).

O funcție prietenă poate fi definită chiar în interiorul clasei; atunci este găsită doar prin argumentele de tipul clasei (un stil recomandat pentru operatori).

Exemple

Exemplul 1: Operator de afișare prieten

#include <iostream>
#include <string>
#include <utility>

class Produs {
public:
    Produs(std::string nume, double pret) : nume_(std::move(nume)), pret_(pret) {}

    friend std::ostream& operator<<(std::ostream& out, const Produs& p) {
        return out << p.nume_ << " (" << p.pret_ << " lei)";
    }

private:
    std::string nume_;
    double pret_;
};

int main() {
    Produs p("Caiet", 8.5);
    std::cout << "Am cumpărat: " << p << '\n';
}

Rezultat

Am cumpărat: Caiet (8.5 lei)

Exemplul 2: Clasă prietenă

Auditor poate citi soldul privat al oricărui Cont, fără ca soldul să devină public pentru restul programului.

#include <print>

class Cont {
public:
    explicit Cont(double sold) : sold_(sold) {}
private:
    double sold_;
    friend class Auditor;
};

class Auditor {
public:
    static bool verifica(const Cont& c) { return c.sold_ >= 0; }
};

int main() {
    Cont bun(150), rau(-20);
    std::println("Cont 1 corect: {}", Auditor::verifica(bun));
    std::println("Cont 2 corect: {}", Auditor::verifica(rau));
}

Rezultat

Cont 1 corect: true
Cont 2 corect: false

Greșeli frecvente

  • Folosești friend ca să ocolești încapsularea peste tot. Dacă multe funcții externe au nevoie de membrii privați, probabil că acele funcții ar trebui să fie metode sau că interfața publică e incompletă.
  • Te aștepți ca o clasă derivată din Auditor să fie și ea prietenă cu Cont. Prietenia nu se moștenește.

Comenzi înrudite

  • operator: Definește ce face un operator (+, ==, <<, [], () etc.) pentru tipurile tale, ca obiectele să se folosească la fel de natural ca numerele.
  • class: Definește un tip nou care grupează date (membri) și funcțiile care lucrează cu ele (metode); baza programării orientate pe obiecte.
  • public, private, protected: Specificatorii de acces: stabilesc cine poate folosi membrii unei clase și cum se moștenește o clasă de bază.