2011-09-02 4 views
19

Ho provato a racchiudere qualcosa di simile ai puntatori di dati condivisi di Qt per i miei scopi, e dopo aver provato ho scoperto che quando veniva chiamata la funzione const, la sua versione non const era scelto invece.Chiamare una funzione const piuttosto che la sua versione non costante

Sto compilando con C++ 0x opzioni, ed ecco un codice minimo:

struct Data { 
    int x() const { 
     return 1; 
    } 
}; 

template <class T> 
struct container 
{ 
    container() { 
     ptr = new T(); 
    } 


    T & operator*() { 
     puts("non const data ptr"); 
     return *ptr; 
    } 

    T * operator->() { 
     puts("non const data ptr"); 
     return ptr; 
    } 

    const T & operator*() const { 
     puts("const data ptr"); 
     return *ptr; 
    } 

    const T * operator->() const { 
     puts("const data ptr"); 
     return ptr; 
    } 

    T* ptr; 
}; 

typedef container<Data> testType; 

void testing() { 
    testType test; 
    test->x(); 
} 

Come si può vedere, Data.x è una funzione const, quindi l'operatore -> dovrebbe essere chiamato il primo. E quando commento quello non const, si compila senza errori, quindi è possibile. Eppure le mie stampe terminali:

"dati PTR non const"

Si tratta di un bug di GCC (ho 4.5.2), o c'è qualcosa che mi manca?

risposta

17

Se si dispone di due overload che differiscono solo nella loro const -ness, quindi il compilatore risolve la chiamata in base al fatto *this è const o meno. Nel codice di esempio, test non è const, pertanto viene chiamato il sovraccarico non const.

Se avete fatto queste cose:

testType test; 
const testType &test2 = test; 
test2->x(); 

si dovrebbe vedere che l'altro di sovraccarico viene chiamato, perché è test2const.

+2

in modo che il compilatore preferisca chiamare il sovraccarico non costante se l'oggetto non è dichiarato const, anche se potrebbe chiamare il sovraccarico const? – coyotte508

+2

@ coyotte508: Precisamente. Il sovraccarico non-'' 'è considerato una corrispondenza migliore. –

1

Ma testType non è un oggetto const.

Così chiamerà la versione non const dei suoi membri.
Se i metodi hanno esattamente gli stessi parametri, deve scegliere quale versione chiamare (quindi usa questo parametro (quello nascosto)). In questo caso questo non è const, quindi ottieni il metodo non-const.

testType const test2; 
test2->x(); // This will call the const version 

Questo non influisce sulla chiamata a x() come è possibile chiamare un metodo const su un oggetto non const.

2

Non importa se Data::x è una funzione costante o meno. L'operatore chiamato appartiene alla classe container<Data> e non alla classe Data e la sua istanza non è costante, pertanto viene chiamato l'operatore non costante. Se fosse disponibile solo un operatore costante o l'istanza della classe fosse costante, sarebbe stato chiamato l'operatore costante.

4

test è un oggetto non const, quindi il compilatore trova la corrispondenza migliore: la versione non const. È possibile applicare constness con static_cast però: static_cast<const testType&>(test)->x();

EDIT: Per inciso, come si sospetta il 99,9% del tempo si pensa di aver trovato un bug del compilatore è necessario rivedere il codice come probabilmente c'è qualche strano capriccio e il compilatore sta infatti seguendo lo standard.

+0

+1 per il commento "Probabilmente non hai trovato un bug nel compilatore" – MikMik

Problemi correlati