2009-06-17 25 views
7

Estaba leyendo las preguntas más frecuentes sobre C++ 0x de Stroustrup y me quedé atascado con este código. Considere el siguiente códigoReglas de alcance al heredar - C++

struct A 
{ 
    void f(double) 
    { 
     std::cout << "in double" << std::endl; 
    } 
}; 

struct B : A 
{ 
    void f(int) 
    { 
     std::cout << "in int" << std::endl; 
    } 
}; 


int main() 
{ 
    A a; a.f(10.10); // as expected, A.f will get called 
    B b; b.f(10.10); // This calls b.f and we lose the .10 here 
    return 0; 
} 

Mi opinión fue cuando se hereda un tipo, a todos los miembros protegidas públicas y serán accesibles desde la clase derivada. Pero según este ejemplo, parece que estoy equivocado. Esperaba que b.f llame a las clases base f. Me dieron el resultado esperado por el cambio de la clase derivada como

struct B : A 
{ 
    using A::f; 
    void f(int) 
    { 
     std::cout << "in int" << std::endl; 
    } 
}; 

Preguntas

  1. ¿Por qué no funciona en el primer código?
  2. ¿Qué sección en el estándar de C++ describe todas estas reglas de alcance?
+0

pregunta qood .. + 1 – Warrior

Respuesta

4

El primer código funciona como C++ está diseñado para funcionar.

La resolución de sobrecarga sigue un conjunto de reglas muy complicado. Desde la biblia C++ de Stroustrup 15.2.2 "[A] las mbiguidades entre funciones de diferentes clases base no se resuelven en base a los tipos de argumentos".

Continúa explicando el uso de "usar" como lo ha descrito.

Esta fue una decisión de diseño en el idioma.

Tiendo a seguir el libro de Stroustrup en lugar del estándar, pero estoy seguro de que está ahí.

[Editar]

Aquí es (de la norma):

Capítulo 13

Cuando dos o más diferentes declaraciones se especifican para un único nombre en el mismo alcance, que el nombre es dice que es sobrecargado.

Y entonces:

13.2 Declaración a juego

1 Dos declaraciones de función del mismo nombre se refieren a la misma función si están en el mismo ámbito y tienen declaraciones de parámetros equivalentes (13,1). Un miembro de función de una clase derivada no tiene el mismo alcance que un miembro de función de con el mismo nombre en una clase base.

+0

valdría la pena añadir el ejemplo fijo (es decir, con el uso de A :: foo). –

1

En el primer caso, el método de la clase base 'f' es ocultos por el método de la clase derivada.En C++ no hay sobrecarga en todos los ámbitos; es por eso que no se llama. El estándar C++ explica todas las reglas de búsqueda de nombre de miembro en el sección 10.2 Buscar nombre de miembro [class.member.lookup]. HTH

1

La primera versión del código realmente debe llamar a B :: f. Usted redefine el símbolo "f" en la estructura "B", por lo que oculta el símbolo original "f" de la estructura "A". No es una sobrecarga, como puede parecer.

Cuando el compilador cumple b.f(), busca en la estructura "B" un símbolo "f". Está presente allí, por lo que el compilador decide llamar a B :: f (int), convirtiendo el doble en int. No ve la necesidad de escanear la clase principal para una función más adecuada ...

Sin embargo, cuando agrega "using A :: f", es una directiva explict para el compilador escanear una clase principal para el símbolo " F". Ahora, la clase B tiene dos funciones sobrecargadas: para int y para doble.

también creo, que se podría escribir bA :: f() sin utilizar "por medio de" directiva en el ejemplo originales ...