[C++] ¿Por qué una función anulada en la clase derivada oculta otras sobrecargas de la clase base?


Answers

Las reglas de resolución de nombres dicen que la búsqueda de nombres se detiene en el primer ámbito en el que se encuentra un nombre coincidente. En ese punto, las reglas de resolución de sobrecarga se activan para encontrar la mejor coincidencia de funciones disponibles.

En este caso, gogo(int*) se encuentra (solo) en el ámbito de la clase Derivada, y como no hay una conversión estándar de int a int *, la búsqueda falla.

La solución es traer las declaraciones Base a través de una declaración de uso en la clase Derivada:

using Base::gogo;

... permitiría que las reglas de búsqueda de nombres encuentren a todos los candidatos y, por lo tanto, la resolución de sobrecarga procedería tal como esperabas.

Question

Considera el código:

#include <stdio.h>

class Base {
public: 
    virtual void gogo(int a){
        printf(" Base :: gogo (int) \n");
    };

    virtual void gogo(int* a){
        printf(" Base :: gogo (int*) \n");
    };
};

class Derived : public Base{
public:
    virtual void gogo(int* a){
        printf(" Derived :: gogo (int*) \n");
    };
};

int main(){
    Derived obj;
    obj.gogo(7);
}

Tengo este error:

>g++ -pedantic -Os test.cpp -o test
test.cpp: In function `int main()':
test.cpp:31: error: no matching function for call to `Derived::gogo(int)'
test.cpp:21: note: candidates are: virtual void Derived::gogo(int*) 
test.cpp:33:2: warning: no newline at end of file
>Exit code: 1

Aquí, la función de la clase derivada está eclipsando todas las funciones del mismo nombre (no la firma) en la clase base. De alguna manera, este comportamiento de C ++ no se ve bien. No es polimórfico.




El ocultamiento de nombres tiene sentido porque evita ambigüedades en la resolución de nombres.

Considera este código:

class Base
{
public:
    void func (float x) { ... }
}

class Derived: public Base
{
public:
    void func (double x) { ... }
}

Derived dobj;

Si Base::func(float) no estaba oculto por Derived::func(double) en Derived, llamaríamos a la función de clase base al llamar a dobj.func(0.f) , aunque un float se puede promocionar a double .

Referencia: http://bastian.rieck.ru/blog/posts/2016/name_hiding_cxx/