2013-03-14 17 views
8

La mia domanda è la differenza tra:C++ due versioni di sovraccarico operatore pedice

const T& operator[](const int nIndex) const; 

e:

T& operator[](const int nIndex); 

Perché dovrei bisogno di ciascuno di essi definito in una classe, qual è lo scopo? Non basterebbe il secondo?

+0

possibile duplicato di [cosa significa const in C++ in luoghi diversi] (http://stackoverflow.com/questions/10482455/what-does-const-mean-in-c-in-different-places) – juanchopanza

risposta

15

Una dichiarazione di funzione membro con const alla fine di esso permette che funzione da chiamare anche su un oggetto const. Questo ha senso solo per le funzioni membro che non modificano lo stato dell'oggetto.

Diciamo che la classe che hai sovraccaricato questi operatori si chiama X. Presumibilmente si comporta un po 'come un contenitore, dando accesso agli elementi che contiene attraverso questo operator[].

Ora diciamo che l'utente vuole utilizzare un const X:

const X x = /* fill it */; 
use(x[0]); 

qualora l'utente essere consentito di fare questo? Probabilmente. Se vogliono un contenitore che è immutabile, allora lascialo avere. Se non hai fornito la versione const di operator[], non sarebbero in grado di farlo. Dopo tutto non stanno cercando di modificare il contenitore, stanno solo guardando il suo contenuto.

Ora perché la versione const di operator[] restituisce un riferimento const? Perché deve. Restituisce un riferimento a un membro della classe stessa. Se il contenitore è stato const e restituito un non const di riferimento, il chiamante sarebbe in grado di modificare i suoi interni semplicemente utilizzando questo operatore:

const X x = /* fill it */; 
x[0].modify(); 

Oddio, abbiamo modificare lo stato di x anche se è const. Questo sarebbe male e in effetti il ​​compilatore non ti lascerà nemmeno fare.

+0

I aggiungerei che 2 metodi simili sovraccaricati (const e non-const) sono spesso un boilerplate in C++ –

+0

@sftrabbit: follow-up stupido: ho capito correttamente che devo ancora definire due corpi separati delle versioni const e non-const degli operatori e che questi corpi saranno esattamente gli stessi? Fondamentalmente, smth come return MyDataStructure [nIndex]? –

+1

@SimonRighley Sì, è necessario definirli entrambi. Tu * potresti * definire la versione non-'conven» in termini della versione 'const', ma poi dovresti fare un' const_cast'. Stai meglio avendo solo la doppia implementazione. –

2

Se l'oggetto a cui si sta accedendo è const, non si desidera poterlo modificare. Il compilatore non consente di chiamare la versione non const della funzione.

const vector<int> mints; 

mints[3] = 5; // not allowed by compiler 
3

Queste sono funzioni membro di una classe, e la versione saranno scelti in base al fatto che in classe utilizzato come contesto const.

Questa versione verrà chiamata quando [] viene utilizzato su un oggetto in un contesto const. Conserva l'elemento const dell'elemento restituito.

const T& operator[](const int nIndex) const; 

Questa versione verrà chiamato quando [] viene utilizzato su un oggetto non const. Si specifica che quando l'oggetto non è const, si otterrà un elemento che è possibile modificare, il codice che consente come myObject[0] = 10;

T& operator[](const int nIndex); 
2

Il primo

const T & operatore [] (const int nIndex) const;

è un metodo costante (funzione), ovvero garantisce che non cambierebbe alcuna variabile membro della classe (a meno che non sia mutabile).

Restituisce anche un oggetto costante che significa che è possibile chiamare solo la funzione costante i.e è possibile chiamare solo le funzioni che hanno const alla fine simile a quella sopra.

T & operatore [] (const int nIndex);

Questo metodo può modificare le variabili membro e restituire un oggetto che può chiamare qualsiasi metodo di classe.

Abbiamo bisogno di entrambi perché l'oggetto costante userebbe il metodo costante e non costante userebbe l'altro.