Función con el mismo nombre pero firma diferente en la clase derivada no encontrada

Resuelto Igor asked hace 15 años • 2 respuestas

Tengo una función con el mismo nombre, pero con diferente firma en una clase base y derivada. Cuando intento utilizar la función de la clase base en otra clase que hereda de la derivada, recibo un error. Vea el siguiente código:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

Recibo el siguiente error del compilador gcc:

In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)

Si elimino int foo(int i){};de la clase Bo si le cambio el nombre foo1, todo funciona bien.

¿Cuál es el problema con esto?

Igor avatar Jan 04 '09 22:01 Igor
Aceptado

Esto se debe a que la búsqueda de nombres se detiene si encuentra un nombre en una de sus bases. No buscará más allá en otras bases. La función en B oculta la función en A. Debe volver a declarar la función de A en el alcance de B, de modo que ambas funciones sean visibles desde B y C:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
    using A::foo;
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

Editar: La descripción real que proporciona el Estándar es (de 10.2/2):

Los siguientes pasos definen el resultado de la búsqueda de nombres en el ámbito de una clase, C. Primero, se considera cada declaración del nombre en la clase y en cada uno de sus subobjetos de clase base. Un nombre de miembro f en un subobjeto B oculta un nombre de miembro f en un subobjeto A si A es un subobjeto de clase base de B. Cualquier declaración que esté así oculta se elimina de la consideración. Cada una de estas declaraciones que fue introducida mediante una declaración de uso se considera que proviene de cada subobjeto de C que es del tipo que contiene la declaración designada por la declaración de uso.96) Si el conjunto resultante de declaraciones no son todos de subobjetos del mismo tipo, o el conjunto tiene un miembro no estático e incluye miembros de distintos subobjetos, hay ambigüedad y el programa está mal formado. De lo contrario, ese conjunto es el resultado de la búsqueda.

Tiene lo siguiente que decir en otro lugar (justo encima):

Para una expresión de identificación [ algo como "foo" ], la búsqueda de nombres comienza en el ámbito de clase de this; para una identificación calificada [ algo como "A::foo", A es un especificador de nombre anidado ], la búsqueda de nombre comienza en el alcance del especificador de nombre anidado. La búsqueda de nombres se realiza antes del control de acceso (3.4, cláusula 11).

([...] puesto por mí). Tenga en cuenta que eso significa que incluso si su foo en B es privado, el foo en A aún no se encontrará (porque el control de acceso ocurre más adelante).

Johannes Schaub - litb avatar Jan 04 '2009 15:01 Johannes Schaub - litb

Las funciones en clases derivadas que no anulan funciones en clases base pero que tienen el mismo nombre ocultarán otras funciones con el mismo nombre en la clase base.

Generalmente se considera una mala práctica tener funciones en clases derivadas que tengan el mismo nombre que funciones en la clase de bajo y que no estén destinadas a anular las funciones de la clase base, ya que lo que está viendo generalmente no es un comportamiento deseable. Generalmente es preferible dar diferentes nombres a diferentes funciones.

Si necesita llamar a la función base, deberá delimitar el alcance de la llamada mediante A::foo(s). Tenga en cuenta que esto también desactivaría cualquier mecanismo de función virtual al A::foo(string)mismo tiempo.

CB Bailey avatar Jan 04 '2009 15:01 CB Bailey