2009-12-13 16 views
53

Ho scritto il seguente codice per spiegare il mio problema. Se commento la riga 11 (con la parola chiave "using"), il compilatore non compila il file e visualizza questo errore: invalid conversion from 'char' to 'const char*'. Sembra non vedere il metodo void action(char) della classe Parent nella classe Son.Perché dovrei usare la parola chiave "using" per accedere al metodo della mia classe base?

Perché il compilatore si comporta in questo modo? O ho fatto qualcosa di sbagliato?

class Parent 
{ 
    public: 
     virtual void action(const char how){ this->action(&how); } 
     virtual void action(const char * how) = 0; 
}; 

class Son : public Parent 
{ 
    public: 
     using Parent::action; // Why should i write this line? 
     void action(const char * how){ printf("Action: %c\n", *how); } 
}; 

int main(int argc, char** argv) 
{ 
    Son s = Son(); 
    s.action('a'); 
    return 0; 
} 
+0

Per favore dimmi: cosa succede se si rimuove const in "const char how"? –

+24

Non è necessario digitare 'Son s = Son();'. Questo crea solo un temporaneo e quindi chiama il costruttore di copie. Basta digitare 'Son s;' –

+3

Otteniamo questa domanda molto: [http://stackoverflow.com/questions/1835988](http://stackoverflow.com/questions/1835988) [http://stackoverflow.com/ questions/411103] (http://stackoverflow.com/questions/411103) [http://stackoverflow.com/questions/1480085](http://stackoverflow.com/questions/1480085) [http: // stackoverflow. it/questions/1799497] (http://stackoverflow.com/questions/1799497) [http://stackoverflow.com/questions/888235](http://stackoverflow.com/questions/888235) [http: // stackoverflow.com/questions/72010](http://stackoverflow.com/questions/72010) –

risposta

47

Il action dichiarata nella classe derivata nasconde la action dichiarato nella classe base. Se si utilizza action su un oggetto Son, il compilatore cercherà nei metodi dichiarati in Son, ne troverà uno chiamato action e lo userà. Non continuerà a cercare nei metodi della classe base, poiché ha già trovato un nome corrispondente.

Quindi quel metodo non corrisponde ai parametri della chiamata e si ottiene un errore.

Vedere anche lo C++ FAQ per ulteriori spiegazioni su questo argomento.

+8

@sth Buono a sapersi. ma questo, posso dire, una caratteristica di C++ o qualche tipo di bug? questo non rovina l'intera idea dell'eredità? solo chiedendo .. – Anubis

+0

L'abbinamento del nome è stato eseguito usando il nome storpiato, l'overloading del metodo ha un ruolo qui, o è la prima funzione chiamata che ha il nome "action" e basta? – tmaric

+3

@ Anubis: la regola semplifica la ricerca del nome. Senza di esso, il compilatore dovrebbe passare sopra l'albero di ereditarietà completo quando deve risolvere il nome di una funzione membro (potrebbero esserci sovraccarichi della funzione in alcune classi base).Con la regola, il compilatore può smettere di guardare il resto dell'albero di ereditarietà una volta trovata una classe contenente un nome appropriato. Il programmatore si trova nella stessa situazione. Guardando la classe derivata può essere sicuro che la funzione definita lì verrà chiamata, senza dover sapere se alcune classi base potrebbero contenere una funzione diversa con lo stesso nome. – sth

15

Sorprendentemente questo è un comportamento standard. Se una classe derivata dichiara un metodo con lo stesso nome di un metodo definito dalla classe base, il metodo della classe derivata "nasconde la classe base".

Vedi C++ FAQ

5

Una nota di cautela: la necessità di utilizzare un "utilizzo" in questa situazione è una bandiera rossa che il codice potrebbe confondere gli altri sviluppatori (dopotutto ha confuso il compilatore!). È probabile che tu debba rinominare uno dei due metodi per rendere la distinzione chiara ad altri programmatori.

Una possibilità:

void action(const char how) 
{ 
    takeAction(&how); 
} 
void action(const char * how) 
{ 
    takeAction(how); 
} 
virtual void takeAction(const char * how) = 0; 
3

Se in una qualsiasi funzione di sovraccarico classe derivata viene ridefinito poi tutta la funzione in overload nella classe base è nascosto. Un modo per includere entrambe le funzionalità è evitare l'overloading delle funzioni nelle classi. oppure È possibile utilizzare la parola chiave using come utilizzata.

Problemi correlati