Pregunta

Estaba leyendo las preguntas frecuentes de C ++ 0x de Stroustrup y me quedé atascado con este código. Considere el siguiente código

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 entendimiento fue cuando un tipo se hereda, todos los miembros protegidos y públicos serán accesibles desde la clase derivada. Pero de acuerdo con este ejemplo, parece que estoy equivocado. Esperaba que b.f llame a las clases base f . Obtuve el resultado esperado al cambiar la clase derivada como

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

Questions

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

Solución

El primer código funciona ya que c ++ está diseñado para funcionar.

La resolución de sobrecarga sigue un conjunto de reglas muy complicado. De la biblia c ++ 15.2.2 de Stroustrup " [A] mbiguities entre funciones de diferentes clases base no se resuelven en función de los tipos de argumentos. & Quot;

Continúa explicando el uso de " utilizando " como has 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í está (de la norma):

Capítulo 13

Cuando se especifican dos o más declaraciones diferentes para un solo nombre en el mismo ámbito, se dice que ese nombre es sobrecargado.

Y luego:

13.2 coincidencia de declaración

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 está en el mismo ámbito que un miembro de función de el mismo nombre en una clase base.

Otros consejos

Es porque A :: f está " oculto " en lugar de " sobrecargado " o " invalidado " ;. Referir:

http://www.parashift.com /c++-faq-lite/strange-inheritance.html#faq-23.9

Busca resolución de sobrecarga . Una pregunta similar, pero no idéntica .

En C ++, no hay sobrecarga en todos los ámbitos, el ámbito en clases derivadas no es una excepción. (Según el lenguaje de programación C ++)

Para obtener más información, consulte http: //www.research. att.com/~bs/bs_faq2.html#overloadderived

En el primer caso, el método de clase base 'f' está oculto por el método de clase derivado. En C ++ no hay sobrecarga en todos los ámbitos; Por eso no se llama. El estándar de C ++ explica todas las reglas de búsqueda de nombres de miembros en la sección 10.2 Búsqueda de nombres de miembros [class.member.lookup] . HTH

La primera versión del código debería llamar B :: f. Usted vuelve a definir el símbolo " f " in struct " B " ;, por lo que oculta el símbolo original " f " de estructura " A " ;. No es una sobrecarga, como puede parecer.

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

Sin embargo, cuando agrega " utilizando A :: f " ;, es una directiva explícita para que el compilador escanee una clase padre para el símbolo " f " Ahora, la clase B tiene dos funciones sobrecargadas: para int y para doble.

También creo que podrías escribir b.A :: f () sin usar " usando " Directiva en el ejemplo original ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top