2012-07-25 16 views
10

Eventuali duplicati:
Functions with const arguments and OverloadingPerché i qualificatori const sono argomenti della funzione utilizzati per la risoluzione dell'overload?

Io sono bello confuso dal sovraccarico e le regole di dichiarazione const. Qui ci sono due cose che mi incuriosiscono, forse puoi aiutarmi a trovare l'incomprensione più profonda nella mia testa che mi fa sembrare sconcertante. ;)

Prima edizione:

mio compilatore permette questo:

void f(int & x) { 
    std::cout << "plain f" << std::endl; 
} 
void f(const int & x) { 
    std::cout << "const f" << std::endl; 
} 

Ma il seguente causa un errore di compilazione (funzione ha già un corpo):

void f(int x) { 
    std::cout << "plain f" << std::endl; 
} 
void f(const int x) { 
    std::cout << "const f" << std::endl; 
} 

che suppongo ha senso perché pensavo che il const fosse solo lì per dire al compilatore che l'oggetto che viene passato non è cambiato e nel secondo caso viene comunque copiato. Ma se questo è corretto, allora perché posso sovraccaricare le funzioni usando const?

In altre parole, perché se io uso la versione compilazione e chiamare le funzioni in questo modo:

int x1 = 5; 
    const int x2 = 5; 
    f(x1); 
    f(x2); 

ottengo "plain f" e "f const" invece di "f const" due volte? A quanto pare ora sto anche usando il const per dire al compilatore quale funzione chiamare non solo che il riferimento non cambia. Questo diventa più confuso perché se rimuovo la versione "semplice" funziona perfettamente e chiama la versione "const" due volte.

Ora qual è la mia domanda attuale? Mi piacerebbe sapere quali sono le idee dietro questo comportamento perché altrimenti memorizzarlo è molto difficile.

+0

I qualificatori 'const' di livello superiore sui parametri di funzione sono _removed_ quando si determina la firma di una funzione. 'void f (int)' e 'void f (const int)' si riferiscono alla stessa funzione. Il livello principale 'const' non viene utilizzato per la risoluzione di sovraccarico. 'const' più in basso di un tipo derivato (come in' const int & ') influenza i tipi di parametri di funzione e quindi la firma della funzione. –

+0

Vedi anche: http://stackoverflow.com/questions/4212932/defining-a-function-with-different-signature –

+0

@CharlesBailey Grazie per i collegamenti. In qualche modo non ho trovato quelli, mi dispiace. – Sarien

risposta

1

ho pensato che il const era lì solo per dire al compilatore che l'oggetto essendo passato non è cambiato e nel secondo caso esso viene copiato in ogni caso

Lei ha ragione. Perché nel secondo caso viene comunque copiato, e quindi lo const non fa alcuna differenza per il chiamante, lo standard definisce che void f(const int x) e void f(int x) hanno la stessa firma. Quindi si scontrano, stai cercando di definire la stessa funzione due volte.

Perché nel primo caso non è copiato in ogni caso, void f(const int &x) e void f(int &x) hanno diversi firme. Quindi sovraccaricano.

Nel primo caso, è vietato chiamare la versione di int&f con x2 come argomento, perché sarebbe creare un riferimento non const a un oggetto const senza alcun cast esplicito in vista. In questo modo si sconfigge lo scopo del sistema const (che è quello che se si vuole infrangere const-safety, bisogna farlo esplicitamente con un cast). Quindi ha senso avere sovraccarichi costanti e non costanti di funzioni con parametri di riferimento.

Nel secondo caso, non esiste alcuna relazione tra la costanza della sorgente di una copia e la costanza della destinazione. È possibile inizializzare una variabile const da una non const o da una const const. Questo non causa problemi e non infrange la sicurezza costante. Ecco perché lo standard lo rende utile definendolo definendo che le due versioni "diverse" di f sono in realtà la stessa funzione.

+0

Quindi forse la mia domanda si riduce a: Perché dovrei voler usare la funzione constless (quando si chiama)? Per elaborare un po ': perché dovrei voler chiamare f (int & x) quando ho f (int const & x)? Sembra difficile distinguere quale si chiami e completamente confuso. – Sarien

+0

Suppongo che si riferisca al fatto che il "const" nella mia testa mi dice qualcosa sul comportamento della funzione (non cambia questo riferimento) e ora viene usato per decidere la funzione _questo_ invece di utilizzarla. – Sarien

+0

@CorporalTouchy: tu * non puoi * chiamare la funzione non-const con un argomento const, perché è permesso fare qualcosa come 'void f (int & x) {x = 6;}'. Ecco perché il sovraccarico 'f (const int & x) 'viene selezionato quando lo passi' x2'. Quando lo si passa 'x1', viene selezionato il sovraccarico non costante, poiché, in effetti, fornendo un argomento non costante come argomento, si autorizza a modificare la variabile. In effetti il ​​tuo corpo funzione non modifica nulla, quindi in questo caso certo, è difficile capire perché la differenza è importante. –

4

n3337 13,1

[Nota: Come specificato in 8.3.5, dichiarazioni di funzione che hanno dichiarazioni di parametri equivalenti dichiarare la stessa funzione e non può pertanto essere sovraccaricato: ffer solo in presenza o assenza

- Dichiarazioni di parametri che di3 di const e/o volatile sono equivalenti. Cioè, gli identificatori di tipo volatile const e per ogni tipo di parametro vengono ignorati quando determina quale funzione viene dichiarata, definita o chiamata. [ Esempio:

typedef const int cInt; 
int f(int); 
int f(const int); // redeclaration of f(int) 
int f(int) { /* ... */ } // definition of f(int) 
int f(cInt) { /* ... */ } // error: redefinition of f(int) 

- fine esempio] Solo il const e tipo-specificatori volatili a livello più esterno del tipo di parametro specifica dettagliata vengono ignorati in questo modo ; gli identificatori di tipo const e volatile sepolti all'interno di un parametro con le specifiche di tipo sono significativi e possono essere utilizzati per distinguere le dichiarazioni di funzioni sovraccaricate .124 In particolare, per qualsiasi tipo T, " " puntatore a T, "puntatore a const T" e "Puntatore a T volatile" sono considerati distinti tipi di parametri, come "riferimento a T", " ", riferimento a const T, "e" riferimento a T. volatile.”

+0

Sarei ancora interessato a un motivo per questo comportamento in quanto sembra essere un doppio significato confuso per const. (Mi piacerebbe sapere perché è definito così nello standard). – Sarien

+2

@CorporalTouchy: quando si passa un parametro in base al valore, si crea una copia. Indipendentemente dal fatto che la copia sia 'const' non ha alcuna influenza sul comportamento del codice chiamante, quindi non vi è alcun motivo per distinguerli dal lato chiamante. –

Problemi correlati