2011-01-12 6 views
6
struct level0 
{ 
    virtual void foo() = 0; 
}; 

struct level1 : level0 
{ 
    virtual void foo() { cout <<" level1 " << endl; } 
}; 

struct level2 : level1 
{ 
    virtual void foo() { cout <<" level2 " << endl; } 
}; 

struct level3 : level2 
{ 
    using level1::foo; 
}; 

int main() 
{ 
    level1* l1 = new level3; 
    l1->foo(); 
    level3 l3; 
    l3.foo(); 
    return 0; 
} 

el código anterior con gcc da¿Se supone que una declaración de uso oculta una función virtual heredada?

level2 
level1 

pero en ICC da

level2 
level2 

cuál es la correcta o es indefinido por la norma?

Editar: Esto demuestra que hay un error con seguridad, considere la siguiente función principal

int main() 
{ 
    level3 l3; 
    l3.foo();    // This prints level1 

    level3* pl3 = &l3; 
    pl3->foo();    // This prints level2 

    level3& rl3 = l3; 
    rl3.foo();    // This prints level1 

    level3& rpl3 = *pl3; 
    rpl3.foo();    // This prints level2 

    return 0; 
} 

Así mismo objeto cuando se utiliza directamente produce resultados diferentes y cuando se utiliza a través de un puntero del mismo tipo produce resultados diferentes !!!

+0

Supongo que GCC es correcto, pero no estoy seguro. –

+0

Es curioso, solo estaba investigando esto ayer. – aschepler

+0

He confirmado el comportamiento con TDM MinGW g ++ 4.4.1. Es un error de g ++, por favor repórtalo. Cheers & hth., –

Respuesta

5

Un ejemplo en la sección estándar 10.3p2 deja en claro que al usar las declaraciones no se reemplazan las funciones virtuales.

Esto es known g++ bug.

Como ha notado, al llamar a la función miembro a través de una referencia o un puntero, en lugar de un caso en el que se conoce el tipo dinámico, la falla no ocurre.

+0

+1 para ref de informe de errores. –

+1

+1 para presupuesto estándar, en cuanto al error: informado en 2004, última actualización en 2006 -> Creo que a nadie le importa realmente, dado el trabajo fácil que existe :) –

0

La manera de conseguir level1 level1 por supuesto sería:

struct level3 : level2 
{ 
    virtual void foo() { level1::foo(); } 
}; 

Tu "por medio de" directiva parece estar informando al compilador que si tiene un nivel 3 y llamar a foo en él, debe invocar el level1 versión, pero no está sobrescribiendo esto a la tabla v.

gcc se ve mal debido a la incoherencia, no estoy seguro acerca de icc porque no sé lo que indica el estándar.

1

using level1::foo; introduce una función foo en level3 clase que hace referencia a level1::foo.

En una declaración using usada como una declaración de miembro, el nombre anidado-especificador debe nombrar una clase base de la clase que se está definiendo. Dicha declaración de uso introduce el conjunto de declaraciones encontradas por la búsqueda de nombre de miembro.

Sin embargo, desde level1::foo es virtual, supongo que al llamarla debe llamar level2::foo, por tanto, la CPI debe ser correcto.

No estoy tan seguro, de todos modos.

Cuestiones relacionadas