2013-06-12 9 views
5

Ho una classe con un colpo di testa in questo modo:public cost non sovrascrive la funzione const privata?

public: 
    const dtMeshTile* getTile(int i) const; 

private: 
    dtMeshTile* getTile(int i); 

Quando provo ad usare in questo modo:

const dtMeshTile* const tile = navmesh->getTile(i); 

sto diventando un " 'dtMeshTile * GetTile (int)' è privato in questo contesto "Come posso specificare la funzione pubblica?

+4

potrebbe .... const * navtmpmesh = navmesh; navmesg-> GetTile (i); lavoro? – UldisK

+5

'const_cast (navmesh) -> getTile();' – BoBTFish

+2

Se non sbaglio, quale funzione il compilatore sceglie di chiamare mai è deciso dal tipo restituito (che è il motivo per cui non puoi avere int foo (int) e void foo (int)). Hai provato a trasmettere il comando navmesh a un puntatore a un oggetto const? Inoltre, il fatto che sia necessario un cast per gestire la scelta della funzione "corretta" probabilmente significa che è necessario rielaborare la propria API. –

risposta

3

considerare:

#include <cstdlib> 

class Bar {}; 
class Foo 
{ 
public: 
    Foo (Bar& bar) 
    : 
     mBar (bar) 
    { 
    } 
    const Bar& get() const 
    { 
     return mBar; 
    } 
private: 
    Bar& get() 
    { 
     return mBar; 
    } 

    Bar& mBar; 
}; 

int main() 
{ 
    Bar bar; 
    Foo foo (bar); 
    Bar& ref = foo.get(); 
} 

Nel punto della chiamata: const Bar& ref = foo.get(); ci si potrebbe aspettare la versione const di get() di essere chiamato, perché si sta assegnando un riferimento const.

Ma questo non è il caso. I tipi restituiti non fanno parte della firma di una funzione (o di un metodo), quindi quando il compilatore sta cercando la funzione da richiamare in un elenco di possibili overload, il tipo restituito non viene considerato. (In effetti, lo standard rifiuta gli overload di funzioni che differiscono solo per il tipo di ritorno.)

Quindi, come fa il compilatore decide quale funzione chiamare? Osservando le informazioni è disponibile ad esso. I sovraccarichi tweo sono identici in termini di parametri (entrambi sono void), quindi l'unica cosa che deve andare è il tipo statico dell'oggetto utilizzato per effettuare la chiamata: foo. Quel tipo statico in questo caso è Foo - decisamente non const.

Pertanto, ha provato a chiamare l'unica funzione possibile: la versione non const di get(). Che, naturalmente, non verrà compilato perché è private.

Per fox questo, il tipo statico può essere modificata per essere un const Foo (o qualcosa di simile), in questo modo:

Foo foo (bar); 
Bar& ref = foo.get(); 

O forse ...

Foo foo (bar); 
const Bar& ref = static_cast <const Foo&> (foo).get(); 

Ma in pratica, vorrei piuttosto consigliare che i nomi di queste funzioni siano ambigui, piuttosto che fare affidamento su tali "trucchi" per contorcere il compilatore nel fare quello che vuoi.

+0

+1 per cambiare i nomi delle funzioni. –

+0

Grazie per la spiegazione molto approfondita. Hai toccato quasi tutto ciò di cui ero confuso. – mpellegr

1

assicurati che navmesh sia const nel contesto della tua chiamata. Ma non lo consiglierei const_cast, potresti leggere questo http://www.parashift.com/c++-faq/overview-const.html.

+0

Perché sei contrario a 'const_cast' in questo caso? Forse non è la soluzione migliore per l'intero problema, ma è un modo ragionevole per chiamare la funzione corretta. – BoBTFish

1

Sei colpito da un flusso di progettazione piuttosto comune, un sovraccarico con semantica mista. Ma immagino che non puoi cambiare la classe, solo aggirarla.

Il tuo problema deriva dalle regole di risoluzione overload. La funzione è selezionata in base agli argomenti. Solo. roba privata/pubblica è ignorata in questa fase. La selezione avviene in base al tipo precedente -> se è const T *, viene selezionata la prima funzione, per T * la seconda.

Il controllo di valutazione viene applicato quindi, quindi per quest'ultimo caso viene visualizzato il report degli errori.Per forzare la funzione desiderata è necessario utilizzare un cast, o meglio creare una funzione wrapper gratuito

const dtMeshTile* getXXXTile(const XXX* p, int i) {return p->getTitle(i);} 

(o una variante ref-taking).

Nella mia base di codici la seconda funzione avrebbe un nome diverso, in quanto ottenere una stringa mutabile è molto diverso nella semantica.

Problemi correlati