Igor
Tengo una función con el mismo nombre, pero con firma diferente en una base y clases derivadas. Cuando trato de usar la función de la clase base en otra clase que hereda de la derivada, recibo un error. Ver 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 clase B
o si le cambio el nombre de foo1
todo funciona bien.
¿Cuál es el problema con esto?
Johannes Schaub – litb
Es porque 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 oscuridad la función en A. Debe volver a declarar la función de A en el ámbito 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):
Los siguientes pasos definen el resultado de la búsqueda de nombres en un ámbito de 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 por 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 es todos de subobjetos del mismo tipo, o el conjunto tiene un miembro no estático e incluye miembros de distintos subobjetos, existe 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 arriba):
Para una expresión de identificación [something like “foo”], la búsqueda de nombres comienza en el ámbito de clase de this; para una identificación calificada [something like “A::foo”, A is a nested-name-specifier], la búsqueda de nombres 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, el foo en A aún no se encontrará (porque el control de acceso ocurre más tarde).
-
litb, gracias por tu respuesta. Pero cuando trato de compilar su código, obtengo: no puedo ajustar el acceso a
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– Igor
4 de enero de 2009 a las 16:52
-
sí, definitivamente un error del compilador. los compiladores antiguos solían usar “A::foo;” en lugar de “usar A::foo;” pero el primero está en desuso en C++.
– Johannes Schaub – litb
4 de enero de 2009 a las 18:29
CB Bailey
Las funciones en clases derivadas que no reemplazan funciones en clases base pero que tienen el mismo nombre esconder 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 bass 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 nombres a diferentes funciones.
Si necesita llamar a la función base, deberá definir el alcance de 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.
-
también lea la respuesta de litdb: puede ‘mostrar’ la función base mediante una cláusula ‘usando A::foo’ en B.
– xtofl
4 de enero de 2009 a las 18:41
-
Cierto, solo estaba buscando una solución que pudiera usarse en el sitio de la llamada, tratando la jerarquía base como fija.
–CB Bailey
4 de enero de 2009 a las 21:07
-
¿Cuál es la base de esta afirmación y seguido por el consejo: “Es generalmente considerado 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 suele ser un comportamiento deseable. Por lo general, es preferible dar diferentes funciones a diferentes nombres“. ¿Qué pasa si están semánticamente haciendo lo mismo? Sin embargo, C ++ le brinda una solución al problema causado por esto, como se explica en la respuesta de Johannes.
– Nawaz
13 de abril de 2018 a las 11:46
-
Functions in derived classes which don't override functions in base classes but which have the same name will hide other functions of the same name in the base class.
Mismo nombre y ¿firma? Estoy un poco confundido porque encontré varios artículos que piensan que esta es la versión de C++ de anulación de métodos (por ejemplo, Anulación de la función g4g en C++–MTV
14 de febrero a las 17:11
Técnicamente, un duplicado de esta pregunta, pero esta tiene un mejor título y respuestas.
– Trovador
1 de septiembre de 2011 a las 20:59