2009-05-20 15 views
40

Duplicar posibles:
C++ overload resolutionAnulación de la función sobrecargada de una base en C++

me encontré con un problema en el que después de mi clase hizo caso omiso de una función de su clase base, todas las versiones sobrecargadas de las funciones fueron escondidas. ¿Esto es por diseño o simplemente estoy haciendo algo mal?

Ej.

class foo 
{ 
    public: 
    foo(void); 
    ~foo(void); 
    virtual void a(int); 
    virtual void a(double); 
}; 

class bar : public foo 
{ 
    public: 
    bar(void); 
    ~bar(void); 
    void a(int); 
}; 

lo siguiente daría un error de compilación diciendo que no hay una función (doble) en la barra.

main() 
{ 
    double i = 0.0; 
    bar b; 
    b.a(i); 
} 
+0

Ayudaría si publicaras (si es posible) el código real. Al código que ha publicado le faltan algunos detalles, como punto y coma después de las definiciones de clase y el tipo de retorno para 'a' en' bar' ... –

+1

No puedo publicar el código real. Agregué los detalles en la publicación, esto no fue realmente un ejercicio de sintaxis. – Greg

+5

http://stackoverflow.com/questions/72010/c-overload-resolution –

Respuesta

62

En la barra de clase, agregue

using foo::a; 

Este es un común 'Gotcha' en C++. Una vez que se encuentra una coincidencia de nombre en el alcance de una clase, no busca más sobre el árbol de herencia para las sobrecargas. Al especificar la declaración 'using', traes todas las sobrecargas de 'a' de 'foo' al alcance de 'bar'. Entonces la sobrecarga funciona correctamente.

Tenga en cuenta que si existe un código que utiliza la clase 'foo', su significado podría cambiarse por las sobrecargas adicionales. O las sobrecargas adicionales podrían introducir ambigüedad y el código no podrá compilarse.Esto se señala en la respuesta de James Hopkin.

+0

¡Explicación perfecta, muchas gracias! – Greg

+3

Vale la pena tener en cuenta el punto de James Hopkin sobre el cambio de significado de un código válido cuando se agregan funciones adicionales a una clase base. –

+0

@Thomas: Editado para agregar ese punto. Gracias. –

18

Esa es la forma en que el lenguaje solía funcionar. Antes de la usando de palabras clave, si sustituimos una función sobrecargada, había que sobrecargarlos todo:

class bar : public foo 
{ 
    public: 
    bar(void); 
    ~bar(void); 
    a(int); 
    a(double d) { foo::a(d); } // add this 
} 

Este pueblo suficientes molesto que el comité idioma añade la usando función, pero algunos viejos hábitos son difíciles ; y los habitués y daga; tener un buen argumento

Como James Hopkins señala, añadiendo usando, el programador está expresando la intención de que la clase derivada, sin previo aviso, añadir los reemplazos futuros de foo :: a() a su lista de firmas aceptables.

Aquí es un ejemplo de lo que él describe: "Derivado :: doble"

#include <iostream> 
class Base { 
public: 
    virtual void f(double){ std::cout << "Base::Double!" << std::endl; } 
    // virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1) 
    virtual ~Base() {} 
}; 

class Derived : public Base { 
public: 
    // using Base::f; // (2) 
    void f(double) { std::cout << "Derived::Double!" << std::endl; } 
}; 

int main(int, char **) { 
    Derived d; 
    d.f(21); 
    return 0; 
} 

La salida será porque el compilador promoverá el argumento entero a un doble. g ++ 4.0.1 -Wall no advertirá que se produjo esta promoción.

Descomentar (1) para simular un cambio futuro a Base agregando el método Base :: f (int). El código se compila, de nuevo, sin previo aviso, incluso con -Wall, y "Derived :: Double!" sigue siendo la salida.

Ahora elimine el comentario (2) para simular una decisión del programador Derived de incluir todas las firmas Base :: f. El código se compila (sin advertencias), pero el resultado ahora es "Base :: Int!".

y daga; No puedo pensar en una palabra en inglés para "aquellos que tienen el hábito" y "adicto" es demasiado fuerte.

+0

Esto no es cierto en absoluto, puede anular muy bien una sola función. –

+0

Mi única defensa es que escribí mucho sobre C++ antes de 1996. Suspiro. –

+0

Ah, los buenos viejos tiempos :) –

11

Es por diseño. La resolución de sobrecarga está restringida a un único alcance. Previene algunos casos desagradables de cambio de significado de significado válido cuando se agregan funciones adicionales a una clase base o al ámbito de espacio de nombres.

Cuestiones relacionadas