2010-01-29 14 views
21

En C++, ¿se invalidará una función miembro de una clase base por su función de clase derivada del mismo nombre, aunque su prototipo (recuento de parámetros, tipo y constness) sea diferente? Supongo que es una pregunta tonta, ya que muchos sitios web dicen que el prototipo de función debe ser el mismo para que eso suceda; pero ¿por qué el código siguiente no se compila? Es un caso muy simple de herencia, creo.Anulación de función y dominio C++

#include <iostream> 
using std::cout; 
using std::endl; 

class A {}; 
class B {}; 

class X 
{ 
public: 
    void spray(A&) 
    { 
     cout << "Class A" << endl; 
    } 
}; 

class Y : public X 
{ 
public: 
    void spray(B&) 
    { 
     cout << "Class B" << endl; 
    } 
}; 

int main() 
{ 
    A a; 
    B b; 
    Y y; 

    y.spray(a); 
    y.spray(b); 

    return 0; 
} 

GCC lanza

error: no matching function for call to `Y::spray(A&)' 
note: candidates are: void Y::spray(B&) 
+0

Obtuve las preguntas frecuentes de C++ que dicen sobre el mismo problema, para una explicación detallada si alguien lo necesita :) http://www.parashift.com/c++faq-lite/strange-inheritance.html#faq- 23.9 – legends2k

+1

Es un poco peligroso decir que las firmas deberían ser las mismas. Las firmas son la base para el nombre de manipulación y vinculación. Dos miembros de diferentes clases siempre tienen diferentes firmas, incluso si una anula la otra. Es mejor decir "los mismos tipos de parámetros, nombres y constness", creo, incluso si es más largo decirlo. –

+0

@litb: ¡Gracias por aclarar! Supongo que 'prototipo' es la palabra adecuada aquí, la he cambiado en la pregunta :) – legends2k

Respuesta

28

El término utilizado para describir este "se oculta", en lugar de "anular". Un miembro de una clase derivada, de forma predeterminada, hará inaccesibles a los miembros de las clases base con el mismo nombre, tengan o no la misma firma. Si desea acceder a los miembros de la clase base, puede incluirlos en la clase derivada con una declaración using. En este caso, añada lo siguiente a class Y:

using X::spray; 
+0

Gracias por la explicación, eso dejó en claro. Funciona cuando agrego la directiva using aquí. Pero cuando cambio las firmas de pulverización para pulverizar (int) en X y rociar (flotar) en Y y llamar a y.spray (1); y y.spray (1.0f); funciona sin la directiva using. ¿Cómo? – legends2k

+2

Wow lo siento, mi mal, todavía está viendo solo el rocío (flotador) de Y, cuando hago y.spray (1); tipo escribe el int para flotar implícitamente. – legends2k

+2

Esta es una de esas respuestas que merece su propia pregunta especial, elaborada con una gran cantidad de polvo de búsqueda para que la gente pueda encontrarla mejor. – Wug

10

que es tan llamado 'ocultar': Y::spray esconde X::spray. Agregar directiva using:

class Y : public X 
{ 
public: 
    using X::spray; 
    // ... 
}; 
5

Las clases son un alcance y ámbito de la clase se anida en su matriz. Tiene exactamente el mismo comportamiento con otros ámbitos anidados (espacios de nombres, bloques).

Lo que sucede es que cuando la búsqueda de nombres busca la definición de un nombre, se ve en el espacio de nombres actual, luego en el espacio de nombres englobing y así sucesivamente hasta que encuentre una definición; la búsqueda se detiene (es decir, sin tener en cuenta las complicaciones introducidas por el argumento búsqueda de nombre dependiente - la parte de las reglas que permite utilizar una función definida en el espacio de nombres de uno de sus argumentos).

+0

Gracias por explicar la razón subyacente detrás de la búsqueda; realmente dice por qué obtuve ese error en primer lugar y por qué la directiva using lo resolvió. – legends2k

Cuestiones relacionadas