A che serve usare la classe di amici C ++?

8

Sto cercando di capire l'amico C ++. Quando è il caso d'uso buono usare amico? Suppongo che se vogliamo lasciare che un'altra classe abbia accesso ad altri attributi di classi, perché non lo rendiamo pubblico o ereditato da quella classe?

Grazie per il tuo aiuto.

    
posta Joshua Partogi 16.04.2011 - 14:05
fonte

8 risposte

13

Rendere un membro della classe public significa garantire a chiunque l'accesso ad esso, interrompendo così completamente l'incapsulamento.

L'ereditarietà da una classe spesso non è auspicabile, se la classe amica non è intesa come sottoclasse. Sottoclassi solo per accedere agli interni di una classe è un grave errore di progettazione. E anche una sottoclasse non può vedere i membri privati della sua classe base.

Un utilizzo tipico di friend è per operatori che non possono essere membri, come operatori di flusso, operator+ ecc. In questi casi, la classe effettiva a cui sono associati non è (sempre) il primo parametro di la funzione, quindi la funzione non può essere implementata come metodo membro.

Un altro esempio è l'implementazione di un iteratore per una raccolta. L'iteratore (e solo l'iteratore) ha bisogno di vedere l'interno della sua collezione genitore, tuttavia non è una sottoclasse della collezione.

    
risposta data 16.04.2011 - 14:54
fonte
2

L'esempio in cui ho visto più spesso le classi di amici usate in C ++ è in testing di unità. I test unitari in genere vogliono sapere tutto sui tuoi interni, ma non fanno parte di te, e non ha senso farli provare ad ereditare da te.

Se non hai familiarità con la scrittura dei test delle unità, ti suggerisco di iniziare subito .

    
risposta data 16.04.2011 - 16:26
fonte
0

Questa domanda dovrebbe essere su stackoverflow. Ad ogni modo, si usa un amico solo quando si desidera condividere le parti private della classe con un'altra classe (o classi) ma non con nessun altro. Se li rendi pubblici tutti possono vedere le tue parti private (gioco di parole ;-P). Esistono due importanti restrizioni che rafforzano la privacy: 1) devi specificare chi è il tuo amico. Nessun altro può essere un amico. 2) non puoi ereditare un comportamento "amichevole" nelle sottoclassi della classe amico

    
risposta data 16.04.2011 - 14:53
fonte
0

Un uso tipico è di concedere l'accesso a funzioni che fanno parte dell'interfaccia di classe, ma grazie ad altre regole non può davvero essere parte della classe corretta. Gli inseritori / estrattori per iostreams sono un esempio classico:

namespace whatever { 
    class something { 
        // ...    
        friend std::ostream &operator<<(std::ostream &os, something const &thing);
        friend std::istream &operator>>(std::istream &is, something &thing);
    };
}

Fare in modo che questi operatori membri della classe lavorino non . Un'operazione di I / O è simile a:

whatever::something thing;

std::cout << thing;

Per un operatore implementato come funzione membro, questo sarebbe risolto come:

std::cout.operator<<(thing);

I.e., la funzione dovrebbe essere un membro di std::cout , non di something . Dato che non vogliamo modificare costantemente std::ostream , la nostra unica opzione ragionevole è di sovraccaricare l'operatore con una funzione libera invece di una funzione membro. Questo ci lascia due possibilità: o ignorare completamente l'incapsulamento e rendere pubblico tutto in classe, oppure mantenerlo privato, ma concedere l'accesso alle poche cose che ne hanno veramente bisogno.

Rendere un altro classe un amico è piuttosto meno comune. In questo caso, di solito stai creando qualcosa sull'ordine di un modulo o sottosistema - un insieme di classi che lavorano insieme e hanno un certo grado di accesso speciale tra loro che non è concesso al mondo in generale.

    
risposta data 16.04.2011 - 17:43
fonte
0

C'è un buon esempio della necessità di classi di amici in questa richiesta per classi amichevoli in C # , una lingua che non le possiede.

Citato all'ingrosso qui:

Access modifiers in .NET were designed with the idea that you can trust your co-workers to know how the code works and hence not slip up and introduce a bug.

This idea is flawed though. Software development is so complicated that an experienced programmer knows not to even trust him/herself! For this reason, experienced programmers prefer to write code which, by design, cannot be broken through accidental misuse. .NET provides the tools to do this when only one class is involved, but the moment a programmer attempts to create a bullet-proof set of two or three interacting classes, this breaks down.

The .NET-intended approach to this is to mark the shared members as "internal", which allows the classes to interact with each others' internals. Unfortunately this also allows every other class in the assembly to mess with the internals, be it by accident or intentionally.

Mads Torgersen, C # Language PM, ha persino risposto a questa proposta, affermando che ritiene che la preoccupazione sia effettivamente valida, ma essendo incerta sull'implementazione specifica suggerita lì.

Il C ++ friend è solo uno dei modi per affrontare il problema descritto.

    
risposta data 16.04.2011 - 22:39
fonte
0

Quando vuoi che le tue classi abbiano relazioni monogame.

es. quando non vuoi che le classi sconosciute accedano ai loro privati, ma i loro partner hanno bisogno di accesso.

    
risposta data 17.04.2011 - 19:32
fonte
0

Ho trovato che le classi di amici in C ++ sono utili dove in Java avrei usato l'accesso ai pacchetti. Cioè, ho un sacco di classi che sono così intimamente correlate da essere scritte e mantenute come un'unità, negli stessi file sorgente. Chiunque lavori a uno di loro sta davvero lavorando su tutti loro. Gli invarianti che mantengono mantengono insieme. Ha senso per loro vedere gli interni di entrambi gli altri in modo che possano mantenere invariato il loro invariato.

Ciò che non ha senso è l'accesso protetto. Se non è sicuro esporre parte del mio internals al pubblico, non è sicuro esporlo a qualunque jackanapes arriva più tardi in un progetto completamente non correlato e afferma di essere la mia sottoclasse. Consentire alle sottoclassi di usare la mia interfaccia pubblica, proprio come tutti gli altri. (A meno che non siano amici, ma in quel caso li ho scritti e li ho implementati nella stessa fonte, quindi difficilmente provengono da qualche altro progetto.)

    
risposta data 03.01.2015 - 02:03
fonte
-1

Diciamo che esiste una funzione esterna che richiede di eseguire operazioni su membri privati o protetti di due classi diverse all'interno del programma. ora, affinché questa funzione abbia accesso e utilizzi effettivamente questi membri della classe, devi renderla amica di entrambe le classi. Tenendo presente che rendendolo un amico di entrambe queste classi non lo rende un membro delle classi, guadagna semplicemente la precedenza per fare riferimento ai membri privati o protetti di queste classi. Posso dire che avresti bisogno di usare una funzione amico quando vuoi operare su oggetti di due classi diverse. Anche se l'uso eccessivo della funzione e della classe di amici può ridurre il valore dell'incapsulamento.

    
risposta data 07.10.2015 - 15:17
fonte

Leggi altre domande sui tag