Tengo una función con el mismo nombre, pero con diferente firma 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 foo1
, todo funciona bien.
Cual es el problema con esto?
Respuestas:
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.
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 nombres diferentes a funciones diferentes.
Si necesita llamar a la función base, deberá establecer el alcance de la llamada utilizando
A::foo(s)
. Tenga en cuenta que esto también deshabilitaría cualquier mecanismo de función virtualA::foo(string)
al mismo tiempo.fuente
Es porque la búsqueda de nombres se detiene si encuentra un nombre en una de sus bases. No mirará más allá de otras bases. La función en B sombrea la función en A. Tienes que 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 da el Estándar es (de 10.2 / 2):
Tiene lo siguiente que decir en otro lugar (justo encima):
([...] puesto por mí). Tenga en cuenta que eso significa que incluso si su foo en B es privado, el foo en A todavía no se encontrará (porque el control de acceso ocurre más tarde).
fuente
void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in
clase B 'debido al método local' int B :: foo (int) 'con el mismo nombre. Tal vez sea porque uso una versión antigua de gcc