2011-08-31 12 views
5

in "The ++ linguaggio di programmazione C", a pagina 265, l'autore fa la seguente dichiarazione:domanda su significati predefiniti per gli operatori

A causa di incidente storico, l'operatori = (assegnazione), & (indirizzo- of), e, (sequencing; §6.2.2) hanno significati predefiniti quando applicati a oggetti di classe. Questi significati predefiniti possono essere fatte inaccessibile agli utenti generici facendoli privato:

Poi viene dato il seguente esempio:

class X { 
private: 
void operator=(const X&); 
void operator&(); 
void operator,(const X&); 
// ... 
}; 

void f(X a, X b) 
{ 
    a = b; // error: operator= private 
    &a;  // error: operator& private 
    a,b; // error: operator, private 
} 

non riesco proprio a capire cosa fanno questi commenti "errore" si riferiscono a? Ciò significa che non dovrei definire una funzione come f o che tutti gli operatori =, & e , dovrebbero essere utilizzati secondo il modo predefinito e non è necessario ridefinirli?

risposta

8

Questo esempio mostra semplicemente un modo per impedire a se stessi o altri sviluppatori del codice di utilizzare operatori, che possono essere utilizzati senza essere stati definiti nella classe, perché vengono generati automaticamente (e hanno significati predefiniti per le operazioni rappresentare).

L'autore di questo esempio ha significato, che se si tenta di assegnare b-a (in linea a = b) causerà un errore, perché l'operatore di assegnazione è privato nella definizione della classe.

Errore simile si verifica in caso di indirizzo-di nella seconda riga e l'operatore virgola nel terzo.

Rendere privati ​​gli operatori/costruttori privati ​​se si sa che non dovrebbero essere utilizzati (o non sono ancora stati implementati) è buono, perché uno potrebbe accidentalmente utilizzare un operatore molto frequente come incarico o copy-constructor, essendo inconsapevole del fatto che il suo comportamento predefinito è in conflitto con il ciclo di vita della classe. Se tale operatore o costruttore viene reso privato all'inizio della progettazione della classe, il compilatore genererà un errore in fase di compilazione invece di eseguire un'operazione potenzialmente pericolosa senza preavviso se il programmatore utilizza accidentalmente il metodo.

Pensate all'operatore di assegnazione di default e al puntatore del membro: copierà il puntatore mentre si potrebbe desiderare che l'oggetto sia il proprietario dei dati. Quindi, dopo che qualcuno ha assegnato un oggetto a un altro senza sapere che l'assegnazione non è stata implementata, si verificherà un doppio errore libero. Invece, se l'operatore è privato, avrai un bel errore e il codice non verrà nemmeno compilato e saprai cosa sta succedendo.

1

Fornire la propria implementazione di qualsiasi operatore è fondamentalmente la stessa implementazione di un metodo di classe. Operatori e metodi sono gli stessi in termini di accessibilità. Quello che fai è negare l'accesso agli operatori dal codice del chiamante.

È assolutamente lo stesso come se si definisse un metodo privato e quindi si provasse a chiamarlo da un codice che non fa parte della classe. Basta rendere pubblici gli operatori e gli errori andranno via.

1

In pratica impedisce a chiunque di creare un oggetto "X" e utilizzando gli operatori "=", "&" e "," su quella classe. Perché l'autore della classe può implementare quegli oggetti con un significato abbastanza diverso da quello che il consumatore della classe potrebbe pensare di fare ... quindi è meglio evitare che vengano usati affatto in caso di ambiguità.

1

La funzione f è un esempio di un utente che tenta di utilizzare gli operatori privati. Ti mostra quale codice è quello che stai impedendo rendendoli privati. Il commento // error indica che un programma che conteneva quella riga non sarebbe stato compilato per il motivo indicato.

5

L'autore intende sottolineare che gli operatori =, & e , sono in genere implicitamente disponibili per una classe.
Quindi se non vuoi che i tuoi oggetti vengano azionati attraverso di loro allora li dichiari come private disabilitando così il loro uso.

Poiché sono dichiarati come private non è possibile accedervi più fuori dalla classe e il compilatore genera un errore di compilazione. La funzione è un esempio che mostra questo.

+0

Trovo che questa risposta sia più chiara di quella con più upvoted: il punto di * significati predefiniti * è che sono presenti e funzioneranno * di default *, e che l'unico modo di * inibire * quel comportamento in C++ 03 è dichiarandoli 'private' (C++ 0x aggiunge la parola chiave' delete') –

0

Prima di discutere l'errore, una chiave qui è capire che queste operazioni saranno rese implicitamente disponibili per la tua classe. Questa è l'essenza del consiglio di Scott Meyers "Sapere quali funzioni C++ scrive e chiama in silenzio."

C++ implementerà automaticamente l'operatore di assegnazione per la classe, ma potrebbe non essere eseguito correttamente (ad esempio, se la classe contiene una variabile membro puntatore). Definendo esplicitamente l'operatore di assegnazione, stai dicendo al compilatore di usare la tua implementazione invece di crearne una per te. E rendendolo privato, si sta essenzialmente disabilitando l'assegnazione di un'istanza di classe a un'altra. Ovunque tu provi a farlo nel tuo codice, il compilatore si lamenterà, il che è una buona cosa se davvero non vuoi che l'assegnazione venga eseguita.

Nella funzione f l'autore mostra che queste istruzioni non verranno compilate a causa di come gli operatori sono definiti nella classe. È perfettamente accettabile ridefinire gli operatori per la classe e talvolta è necessario (ad esempio, implementare una copia profonda di una variabile membro puntatore nella classe). Il punto dell'esempio è mostrare che a) puoi fornire la tua implementazione di questi operatori per la tua classe, eb) a causa di questo hai il controllo su se gli operatori sono supportati e implementati correttamente per la tua classe.