2009-02-25 10 views
30

Si tengo un código como el siguiente:función miembro de C++ anulación virtual y sobrecarga al mismo tiempo

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; 
} 

consigo un error que dice que yo estoy tratando de hacer una conversión no válida de int a void *. ¿Por qué el compilador no puede darse cuenta de que tiene que llamar a B :: f, ya que ambas funciones se declaran como virtuales?


Después de leer la respuesta de jalf fui y la reduje aún más. Este no funciona tan bien. No es muy intuitivo.

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

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


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

    return 0; 
} 

Respuesta

44

La respuesta corta es "porque así es como funciona la resolución de sobrecarga en C++".

El compilador busca las funciones F dentro de la clase C y, si encuentra alguna, detiene la búsqueda e intenta elegir un candidato entre ellas. Solo se ve dentro de las clases base si no se encontraron funciones coincidentes en la clase derivada.

Sin embargo, se pueden introducir de forma explícita las funciones de la clase base en el espacio de nombres derivados de clase:

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

posible que desee agregar un enlace al C++ FAQ en función de ocultación: http://www.parashift.com/c++-faq-lite/strange- inheritance.html # faq-23.9 – greyfade

+0

@jalf: ¿Cuál es la razón del comportamiento de ese compilador? ¿Por qué no buscar clases base para que las funciones se ajusten a la llamada? – Andrew

+0

¿Cuál sería la razón de * que *? El compilador tiene que elegir algún comportamiento, y esto tiene sentido en algunos casos, y parece absurdo en otros. La ventaja de este esquema es que puede optar por el comportamiento de "continuar la búsqueda". Pero si eso fuera entonces no habría forma de optar por no participar y obtener * este * comportamiento. Al final del día, los diseñadores del lenguaje tuvieron que tomar una decisión, y eligieron este comportamiento. :) – jalf

-6

Bueno, creo que en primer lugar que no entendía qué mecanismo virtual o polymorhism. Cuando el polimorfismo se logra solo mediante punteros a objetos. Creo que eres nuevo en C++. Sin utilizar punteros a objetos, no hay ningún significado de polimorfismo o puntero de clase base de uso de palabra clave virtual y le asigna los objetos de clase derivados deseados. Entonces llámalo y pruébalo.

-1

O usted podría hacer esto:

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