2009-02-21 8 views

risposta

3

Si utilizzerà una funzione di amicizia per lo stesso tipo di motivi per cui si utilizzerà una classe di amici, ma in base a una funzione membro (piuttosto che a una classe intera). Alcune buone spiegazioni sono in this thread.

Mentre le funzioni e le classi di amici violano l'incapsulamento, possono essere utili in alcuni scenari. Ad esempio, è possibile consentire a un'imbracatura di test di accedere ai componenti interni della classe per consentire di eseguire test di whitebox. Piuttosto che aprire l'intera classe al cablaggio di prova, è possibile aprire una particolare funzione che accede agli interni richiesti dal cablaggio di test. Mentre questo viola ancora l'incapsulamento, è meno rischioso che aprire l'intera classe.

Vedere anche this article per ulteriori informazioni sulle classi e le funzioni degli amici.

0

A volte il livello di protezione pubblico/privato/protetto non è sufficiente per le situazioni del mondo reale. Pertanto, diamo una piccola clausola di uscita che aiuta senza dover rendere i metodi accessibili pubblicamente.

Personalmente lo uso nello stesso modo in cui Java utilizza il livello di protezione "Pacchetto".
Se ho una classe nello stesso pacchetto che necessita di accesso, prenderò in considerazione l'utilizzo di un amico. Se è una classe in un altro pacchetto, mi chiedo perché mai questa altra classe abbia bisogno di accedere e guardare il mio progetto.

1

Vedi C++ FAQ Lite:

A volte gli amici sono sintatticamente meglio (per esempio, in classe Fred, funzioni friend permettono il parametro Fred di essere secondo, mentre i membri lo richiedono di essere il primo). Un altro buon uso delle funzioni amico sono gli operatori aritmetici binari infissi. Ad esempio, aComplex + aComplex dovrebbe essere definito come amico piuttosto che come membro se si desidera consentire anche aFloat + aComplex (le funzioni membro non consentono la promozione dell'argomento a sinistra, poiché ciò cambierebbe la classe dell'oggetto che è il destinatario della chiamata della funzione membro).

2

Le funzioni e le classi di amici non violano l'incapsulamento quando si tenta di creare un'astrazione o un'interfaccia che deve estendersi fisicamente su più classi o funzioni C++! Ecco perché è stato inventato un amico.

Questi tipi di casi non vengono visualizzati spesso, ma a volte si è costretti a implementare un'astrazione o un'interfaccia con classi e funzioni disparate. L'esempio classico sta implementando un tipo di classe numerica complessa. Le funzioni dell'operatore non membro vengono fornite amicizia con la principale classe di numeri complessi.

Ricordo anche questo durante la programmazione con CORBA in C++. CORBA mi ha costretto a tenere lezioni separate per implementare i dipendenti CORBA. Ma per una parte particolare del nostro software, avevo bisogno di sposarli insieme come un'unica interfaccia. L'amicizia ha permesso a queste due classi di collaborare per fornire un servizio continuo a una parte del nostro software.

Avere la capacità di contrassegnare una particolare funzione membro in un'altra classe come amico della classe può sembrare ancora più strano, ma è solo un modo per controllare l'amicizia. Invece di consentire a tutta l'altra classe "in" come amico, si consente solo l'accesso a una delle sue funzioni membro. Ancora una volta, questo non è comune, ma molto utile quando ne hai bisogno.

+1

+1 per "non violare". Tuttavia, è inutile in caso di molte classi numeriche come complesse, razionali, ... –

0

Un punto che trovo rilevante: le classi membro hanno accesso alle parti private della classe contenente. A volte può essere un'alternativa migliore a "amico".

class A 
{ 
private: 
    int b; 
public: 
    class MemberNotFriend { 
    public: 
    static void test() { 
     A a; 
     a.b = 0; 
    } 
    }; 


}; 


void test() 
{ 
    A::MemberNotFriend::test(); 
} 
0

Ecco un semplice, esempio concreto di come sto utilizzando una funzione friend:

Ho un gioco in cui ogni oggetto sprite mantiene le sue informazioni come X, posizione Y come membri privati. Tuttavia, desidero separare gli oggetti del gioco dal rendering: un oggetto di gioco non ha bisogno dei dettagli esatti di come viene reso. Un oggetto di gioco memorizza solo lo stato del gioco e questo stato di gioco può essere visualizzato in diversi modi.

Quindi la classe dell'oggetto di gioco ha una funzione friend: render(). La funzione render() è implementata al di fuori della classe dell'oggetto del gioco, ma può accedere alle membrafr di posizione della posizione X, come necessario per rendere l'oggetto del gioco.

Problemi correlati