La parola chiave friend consente a una certa funzione o a un'altra classe di avere accesso ai membri privati e protetti della classe in cui è dichiarato friend. Le funzioni friend possono essere sia globali che metodi di altre classi. Questa costruzione consente di implementare funzioni che richiedono accesso allo stato interno della classe, ma che non sono logicamente correlate all'interfaccia di quella classe.
È consigliato utilizzare friend:
Attenzione:
Esempio:
class Box { int width; public: Box(int w): width(w) {} friend void printWidth(const Box &b); }; void printWidth(const Box &b) { std::cout << b.width << std::endl; }
Domanda: Può una funzione friend essere virtuale?
Risposta comune: Sì, poiché friend è un modificatore di funzione.
Risposta corretta: No, le funzioni friend non possono essere virtuali perché non sono membri della classe!
Esempio:
class Example { friend virtual void foo(); // Errore di compilazione: virtual non si applica a friend };
Storia: Quando si progettava una libreria per matrici, tutti gli operatori aritmetici sono stati resi funzioni friend per velocizzare, ma si è dimenticata la compatibilità con la costanza e si è eccessivamente aperto l'accesso ai membri privati. Successivamente, nel progetto, altre funzioni alteravano accidentalmente lo stato interno della Matrix.
Storia: Nella sistema aziendale, le classi helper sono state rese friend tra loro per condividere l'accesso ai membri privati. Questo ha portato a dipendenze cicliche: aggiungere una nuova funzionalità richiedeva di modificare tutte le classi correlate. La successiva refattorizzazione ha richiesto settimane.
Storia: Per i test chiusi, si è deciso di rendere la classe di test friend alla classe di produzione. Quando sono apparsi vari set di unit test, è diventato impossibile tracciare quali metodi privati venivano effettivamente utilizzati; i test hanno iniziato a dipendere dall'implementazione interna, portando a una difficile manutenzione del codice.