Pregunta

Tengo una función con el mismo nombre, pero con firma diferente en una base y clases derivadas. Cuando intento usar 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 B , o si le cambio el nombre de foo1 , todo funciona multa.

¿Cuál es el problema con esto?

¿Fue útil?

Solución

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

En general, se considera una mala práctica tener funciones en clases derivadas que tengan el mismo nombre que las funciones en la clase de graves que no pretenden anular las funciones de la clase base, ya que lo que está viendo no suele ser un comportamiento deseable. Por lo general, es preferible dar diferentes funciones a diferentes nombres.

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

Otros consejos

Es porque la búsqueda de nombres se detiene si encuentra un nombre en una de sus bases. No se verá más allá en otras bases. La función en B sombrea la función en A. Debe volver a declarar la función de A en el ámbito de B, para 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 da el Estándar es (de 10.2 / 2):

  

Los siguientes pasos definen el resultado de la búsqueda de nombres en un ámbito de clase, C. Primero, cada declaración para el   se considera el nombre en la clase y en cada uno de sus subobjetos de clase base. Un nombre de miembro f en un sub-   el objeto 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án tan ocultos se eliminan de la consideración. Cada una de estas declaraciones que fue presentada por un   El uso de la declaración se considera de cada subobjeto de C que es del tipo que contiene la declaración   designación mediante el uso de declaración.96) Si el conjunto resultante de declaraciones no son todas de sub-objetos   del mismo tipo, o el conjunto tiene un miembro no estático e incluye miembros de distintos subobjetos, hay   una ambigüedad y el programa está mal formado. De lo contrario, ese conjunto es el resultado de la búsqueda.

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

  

Para una expresión de identificación [ algo así como " foo " ], la búsqueda de nombres comienza en el alcance de la clase de esto; para un id calificado [ algo así como "A :: foo", A es un especificador de nombre anidado ], la búsqueda de nombre comienza en el ámbito del especificador de nombre anidado. La búsqueda de nombres tiene lugar 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, aún no se encontrará el foo en A (porque el control de acceso ocurre más adelante).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top