2009-02-25 8 views
30

Se ho un codice come questo:funzione di membro C++ di override virtuale e di sovraccarico, allo stesso tempo

struct A { 
    virtual void f(int) {} 
    virtual void f(void*) {} 
}; 

struct B : public A { 
    void f(int) {} 
}; 

struct C : public B { 
    void f(void*) {} 
}; 


int main() { 
    C c; 
    c.f(1); 

    return 0; 
} 

ottengo un errore che dice che sto cercando di fare una conversione non valida da int a void *. Perché il compilatore non può capire che deve chiamare B :: f, dal momento che entrambe le funzioni sono dichiarate come virtuali?


Dopo aver letto la risposta di jalf sono andato e l'ho ridotto ulteriormente. Questo non funziona altrettanto bene. Non molto intuitivo.

struct A { 
    virtual void f(int) {} 
}; 

struct B : public A { 
    void f(void*) {} 
}; 


int main() { 
    B b; 
    b.f(1); 

    return 0; 
} 

risposta

44

La risposta breve è "perché è così che funziona la risoluzione di sovraccarico in C++".

Il compilatore cerca le funzioni F nella classe C e, se ne trova, interrompe la ricerca e tenta di selezionare un candidato tra quelle. Cerca solo nelle classi base se non sono state trovate funzioni di matching nella classe derivata.

Tuttavia, è possibile introdurre in modo esplicito le funzioni di classe base nella classe derivata namespace:

struct C : public B { 
    void f(void*) {} 
    using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution 
}; 
+3

Potrebbe desiderare di aggiungere un link al C++ FAQ sulla funzione nascondersi: http://www.parashift.com/c++-faq-lite/strange- inheritance.html # faq-23.9 – greyfade

+0

@jalf: Qual è la ragione del comportamento di tale compilatore? Perché non cercare le classi base per le funzioni che si adattano alla chiamata? – Andrew

+0

Quale sarebbe la ragione per * che *? Il compilatore deve scegliere un comportamento, e in alcuni casi questo ha senso, e sembra assurdo in altri. Il vantaggio di questo schema è che puoi attivare il comportamento di "continua ricerca". Ma se così fosse, non ci sarebbe alcun modo di rinunciare a questo e ottenere * questo * comportamento. Alla fine della giornata, i progettisti di linguaggi hanno dovuto prendere una decisione e hanno scelto questo comportamento. :) – jalf

-6

Beh penso che prima di tutto non hai capito quale meccanismo virtuale o polymorhism. Quando il polimorfismo viene raggiunto solo utilizzando puntatori di oggetti. Penso che tu sia nuovo in C++. Senza utilizzare puntatori di oggetti, non vi è alcun significato di polimorfismo o parola chiave virtuale utilizzare il puntatore di classe base e assegnare gli oggetti classe derivati ​​desiderati ad esso. Quindi chiama e prova.

-1

Oppure si potrebbe fare questo:

void main() 
{ 
    A *a = new C(); 
    a->f(1); //This will call f(int) from B(Polymorphism) 
} 
Problemi correlati