C ++ ad un amico o non ad un amico

14

Ho una programmazione orientata agli oggetti con il corso c ++ questo semestre all'università e stavamo imparando le funzioni degli amici.

Personalmente non mi piacciono per la loro capacità di aggirare la sicurezza fornita da Encapsulation e Data Hiding, ho letto alcuni articoli su Internet e alcuni hanno pensato che fosse una buona idea con alcuni usi legittimi.

Che cosa direbbe un esperto di OOP sulle fucunzioni di amici in C ++? Dovrei semplicemente passarci sopra o dovrei saperne di più?

    
posta nikhil 04.09.2011 - 09:57
fonte

8 risposte

11

Non è sempre conveniente fare tutte le funzioni relative ai membri di una classe C ++ di quella classe. Ad esempio, immagina un'implementazione dell'algebra vettoriale con moltiplicazione scalare. Vogliamo scrivere:

 double a;
 Vector v, w;
 w = v * a;

Possiamo farlo con una funzione membro:

public class Vector {
 ...
 Vector operator*(double a);
}

Ma vorremmo anche scrivere:

w = a * v

Ciò richiede una funzione gratuita:

 Vector operator*(double a, Vector v)

La parola chiave friend è stata aggiunta a C ++ per supportare questo utilizzo. La funzione libera fa parte dell'implementazione della classe Vector e dovrebbe essere dichiarata nella stessa intestazione e implementata nello stesso file sorgente.

Allo stesso modo possiamo usare friend per semplificare l'implementazione di classi strettamente accoppiate, come una raccolta e un iteratore. Di nuovo, dichiarerei entrambe le classi nella stessa intestazione e le implementerò nello stesso file sorgente.

    
risposta data 04.09.2011 - 20:29
fonte
15

Le funzioni degli amici non sono diverse dalle funzioni dei membri in termini di incapsulamento. Possono, tuttavia, offrire altri vantaggi, come essere più generici, specialmente quando si tratta di modelli. Inoltre, alcuni operatori possono essere specificati solo come funzioni libere, quindi se vuoi che abbiano accesso ai membri, devi friend .

È meglio friend una singola funzione che essere costretti a fare qualcosa che non vuoi essere pubblico. Ciò significa che l'intero mondo può usarlo invece di una sola funzione.

    
risposta data 04.09.2011 - 12:26
fonte
5

Se sei appassionato di ciò che fai, imparerai tutto sul C ++. Scopri a cosa servono, come usarli e poi - e solo allora - decidi di non usarli. Per lo meno, sarai preparato leggendo il codice di qualcun altro che usa questo aspetto del C ++.

    
risposta data 04.09.2011 - 10:12
fonte
5

" Che cosa direbbe un esperto di OOP ... " Dipende principalmente da quanto esperto sia in C ++, che - a parte le sue specifiche - non è (e non vuole essere) una lingua per i puristi.

OOP Gli zeloti non usano il C ++ (preferiscono Smalltalk e come Java).

Gli zelots di programmazione funzionale non usano il C ++ (preferiscono LISP e i suoi successori)

La maggior parte degli esperti OOP non amano la funzione amica semplicemente perché vogliono che la parte OOP del C ++ si comporti come Smalltalk. Ma C ++ non è Smalltalk e non riescono nemmeno a capire che amico non infrange l'incapsulamento , per il semplice motivo che una funzione non può essere amica della tua classe senza che la tua classe lo voglia .

E dal punto di vista "funzionalità", tra a.fn(b) e fn(a,b) non c'è differenza (dove fn è un amico): le parti coinvolte sono le stesse. Semplicemente, una sintassi può essere più adatta di un'altra: se fn è commutativa per quanto riguarda a e b , fn(a,b) è probabilmente più adatto di a.fn(b) (dove sembra avere un "ruolo speciale" che, di fatto, non è così.)

    
risposta data 04.09.2011 - 18:54
fonte
5

Does "friend" violate encapsulation?

No. It does not. "Friend" is an explicit mechanism for granting access, just like membership. You cannot (in a standard conforming program) grant yourself access to a class without modifying its source.

    
risposta data 05.09.2011 - 07:34
fonte
2

Le domande frequenti su C ++ sono succinte:

Use a member when you can, and a friend when you have to.

Le FAQ presentano uno dei modi più utili per pensare all'amicizia:

Many people think of a friend function as something outside the class. Instead, try thinking of a friend function as part of the class's public interface. A friend function in the class declaration doesn't violate encapsulation any more than a public member function violates encapsulation: both have exactly the same authority with respect to accessing the class's non-public parts.

Forse l'uso più comune delle funzioni di amicizia è sovraccarico < < per I / O.

    
risposta data 07.09.2011 - 22:53
fonte
0

Le funzioni amico sono utilizzate al meglio per le definizioni degli operatori definite dall'utente. Sono utili in altre situazioni, ma se ti ritrovi a specificare frequentemente le classi di amici, potresti trovarti in una deviazione di progettazione (solo un buon autocontrollo da utilizzare durante la scrittura del codice).

Fai attenzione alla dichiarazione di "sicurezza" nella domanda originale. I modificatori di accesso sono lì per evitare di scrivere codice errato in caso di incidente, proprio come il compilatore in un certo senso. I modificatori di accesso limitano l'interfaccia e servono a comunicare quali funzioni sono importanti per utilizzare la classe (pubblica e protetta) e quali sono state create come parte della creazione della classe più carina per i manutentori (privati). I modificatori non costituiscono una sicurezza in quanto ci sono molti modi per ottenere dati privati. Ad esempio, ottieni un puntatore alla classe e alle sue dimensioni e vai a pescare.

    
risposta data 05.09.2011 - 22:04
fonte
-2

Le funzioni di amico C ++ sono strettamente correlate alla seguente funzionalità:

  1. funzioni gratuite
  2. funzioni statiche
  3. funzioni amico

Ciò significa che non hanno questo puntatore e quindi sono al di fuori della classe / oggetto. D'altra parte, spesso prendono dei parametri che li rendono di nuovo appartenenti alla classe. Ecco alcuni esempi che chiariscono il link:

class B;
class A {
public:
    friend void f(A &a, B &b);
private:
    int m_a;
};
class B {
public:
   friend void f(A &a, B &b);
private:
   int m_b;
};
void f(A &a, B &b) { /* uses both A's and B's private data */ }

L'unica differenza tra le funzioni statiche e le funzioni di amicizia è che una funzione amico può utilizzare diverse classi.

L'uso del meccanismo di amicizia in c ++ richiede ai programmatori che hanno circa 10-15 anni di esperienza con il modo di programmazione c ++, e quindi inizialmente dovresti evitarlo. È una funzione avanzata.

    
risposta data 04.09.2011 - 11:30
fonte

Leggi altre domande sui tag