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


Tengo una función con el mismo nombre, pero con diferente firma en una base y clases derivadas. Cuando estoy tratando de usar la función de la clase base en otra clase que hereda de la derivada, recibo un error. Véase 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 lo cambio de nombre desde foo1, todo funciona bien.

¿Cuál es el problema con esto?

Author: YSC, 2009-01-04

2 answers

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

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

Si necesita llamar a la función base, necesitará definir el alcance de la llamada usando 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.

 66
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-04 15:22:45

Se debe a que la búsqueda de nombres se detiene si encuentra un nombre en una de sus bases. No mirará más allá en otras bases. La función en B shadows la función en A. Tienes que volver a declarar la función de A en el ámbito de B, de modo que ambas funciones sean visibles desde dentro de 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. 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 son eliminados de la consideración. Cada una de estas declaraciones que fue introducida por un using-declaration se considera que proviene de cada subobjeto de C que es del tipo que contiene la declaraa- tación designada por la declaración de utilización.96) Si el conjunto resultante de las declaraciones no son todas de subobjetos del mismo tipo, o el conjunto tiene un miembro no estático e incluye miembros de subobjetos distintos, 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 de él):

Para una expresión id [algo como"foo" ], la búsqueda de nombres comienza en el ámbito de clase de esto; para una identificación calificada [algo 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 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 tarde).

 93
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-04 15:24:04