Devo usare le classi friend in C ++ per consentire l'accesso ai membri nascosti?

6

Ecco la mia situazione (un semplice esempio).

Dire che ho una classe chiamata HiddenData
Allora ho un'altra classe chiamata StoreHiddenData
E infine una classe chiamata OperateHiddenData

Ecco la cosa, la mia classe chiamata HiddenData ha membri privati che non voglio essere visibile al resto del mondo, ma ho ancora bisogno di classi per essere in grado di operare su membri privati di questo HiddenData classe ( StoreHiddenData e OperateHiddenData per esempio). Mi piacerebbe poter passare questo oggetto a classi diverse che fanno cose diverse su di esso.

Un'altra cosa a cui stavo pensando è creare una forma di handle per questi oggetti HiddenData , ma non riesco a pensare a un modo di usare gli handle senza usare nuovamente le classi friend (in modo da dare alle altre classi l'accesso ad un tabella che contiene ciò a cui puntano le maniglie, senza esporla anche al resto del mondo).

Stavo leggendo la domanda questa su questo sito qualche tempo fa mentre stavo facendo ricerche sull'uso delle classi di amici, e mi ha fatto pensare che usare gli amici fosse il modo migliore per andare.

Se qualcuno ha qualche suggerimento su come eseguire questa attività senza l'uso di classi friend in C ++, o se l'uso di classi friend è una pratica OOP OK, forniscimi qualche suggerimento. Grazie.

EDIT: Immagino che dovrei aggiungere un po 'più di informazioni sul mio problema. Per prima cosa, sto cercando di creare un'API composta da diverse classi che nascondono le loro funzionalità dall'esterno e consentono solo l'accesso alle funzioni pubbliche. All'interno ho strutture dati (o classi, non importa), che devono essere passate a queste diverse classi con funzioni pubbliche. Non voglio che l'esterno abbia accesso a qualsiasi cosa all'interno di queste strutture dati oltre a essere in grado di trasmetterle alle funzioni dell'API. Penso che sia come l'API di Windows, in cui si passano le funzioni di Handles alle API, ma non si possono effettivamente sezionare gli handle nel proprio codice. Bene vorrei fare qualcosa di molto simile, ma pur rimanendo orientato agli oggetti, e NON passare queste strutture dati private in giro per valore perché saranno GRANDI. Grazie ancora.

    
posta contrapsych 29.01.2012 - 19:29
fonte

3 risposte

7

Sarei estremamente cauto sull'uso degli amici. Anche se gli amici hanno il loro tempo e luogo, il più delle volte in cui le persone li usano, è solo un modo conveniente per rompere l'incapsulamento, il che rende il codice facile da scrivere e fornire v1.0 ma come il numero di classi che operano sul vostro HiddenData aumenta e man mano che la dimensione media di quelle classi aumenta, diventerà un incubo da leggere e modificare.

Ho usato amici un paio di volte, ma solo quando le alternative sarebbero state ancora più brutte / difficili da mantenere. Gli iteratori associati a una raccolta specifica sono sicuramente un buon esempio di utilizzo degli amici.

Un altro esempio sono le implementazioni di macchine a stati finiti (FSM), in cui ogni stato è rappresentato da una classe separata. Qui il tuo FSM è la tua vera classe, gli stati sono solo un modo per dividere la logica in unità gestibili, ma generalmente i dati appartengono ancora a FSM.

In conclusione, vorrei appoggiarmi agli amici se la seconda classe è estremamente piccola e non verrà estesa con sempre più funzionalità ad ogni versione. Anche il posizionamento delle due classi dovrebbe essere il più vicino possibile l'uno all'altro. Nel caso degli iteratori di STL, tali classi sono definite all'interno delle proprie classi contenitore. Non avvicinarti di più.

Ci sono diversi modi per implementare il tuo scenario senza dover interrompere l'incapsulamento usando gli amici. Ecco solo alcune delle molte alternative:

  1. Fai nascondere HiddenData. Non dare liberamente riferimenti ad esso. Invece avere un'altra classe adattatore / vista / decoratore (qualunque cosa si voglia chiamare) tra i dati e il pubblico. Questa altra classe garantirebbe che siano consentite solo le operazioni pubbliche. Quindi le tue speciali classi di manipolatore accederanno direttamente alla normale interfaccia pubblica di HiddenData.

  2. Dai un'occhiata a Modello visitatore . Potrebbe essere esattamente ciò di cui hai bisogno. Ti dà la possibilità di aggiungere funzionalità a una classe senza realmente toccare la classe stessa. Quindi, per implementare un altro manipolatore speciale che ha accesso ai dati interni, dovresti creare una nuova classe visitatore e dare un riferimento a un singolo metodo Accept () di HiddenData.

risposta data 30.01.2012 - 03:10
fonte
9

Gli amici C ++ esistono solo per questo. Ogni altro surrogato semplicemente imiterà lo stesso concetto.

  • Ci sono cose che sono per tutti,
  • Cose solo per te (eventualmente ereditate dai tuoi figli)
  • Cose condivise da te con un gruppo ben definito e limitato di persone.

Quelle "persone" sono chiamate "amici". Eliminare quel concetto richiederà che quelle cose diventino pubbliche, o diventino private, ma con le risorse pubbliche da gestire. Devi anche aspettarti che qualcuno sia in grado di fare cose con loro fuori dal tuo controllo.

    
risposta data 29.01.2012 - 23:20
fonte
0

No, non dovresti usare le classi di amici. Esporre l'API pubblica in modo che i tuoi clienti (a questo punto, tu, tramite StoreHiddenData e OperateHiddenData ) siano in grado di modificare il contenuto di Hidden Data con l'uso di un'API. Come ultima risorsa, usa getter e setter. Assicurati di progettare la tua interfaccia pubblica in modo che sia coerente, non solo esporre le funzionalità per poter scrivere codice veloce.

Ma prima di fare qualsiasi cosa, leggi Effective C ++ di Scott Meyers. Risponderà a molte tue domande, ed è sempre utile come libro di riferimento.

    
risposta data 30.12.2014 - 04:35
fonte

Leggi altre domande sui tag