2011-12-03 12 views
6

He encontrado un comportamiento extraño al usar una variable de referencia.Variable de referencia y funciones virtuales

Aquí es implementaciones de clase:

class Base { 
    public: 
     virtual void Method() = 0; 
}; 

class DerivedA : public Base { 
    public: 
     virtual void Method() {} 
} 

class DerivedB : public Base { 
    public: 
     virtual void Method() {} 
} 

He aquí un ejemplo de código que tienen el extraño comportamiento:

void main(int argc, char *argv[]) { 
    DerivedA a; 
    DerivedB b; 
    Base &base = a; 

    base.Method(); // Calls DerivedA::Method 

    base = b; 
    base.Method(); // Calls DerivedA::Method!!! Why doesn't call DerivedB.Method()? 
} 

En conclusión, parece que la tabla de punteros de función virtual "asociado" a la la variable de referencia se determina solo al inicializar la variable de referencia. Si reasigno la variable de referencia, el vfpt no cambia.

lo que sucede aquí?

Respuesta

13

Base &base es una referencia, es decir, alias al objeto a, así que la asignación de base = b es equivalente a a = b, que deja el thingie base siendo el mismo objeto de la misma clase. No es una reasignación de puntero como parece suponer.

+5

¡Creo que esta respuesta merece el tic verde! – Walter

+2

Sí, creo que esta debería ser la respuesta aceptada. – Rafid

+0

Gracias, sin embargo la respuesta aceptada es la pregunta que ha aceptado y que está bien que aceptaba la otra respuesta ;-) –

7

Sólo las referencias se pueden inicializar una vez. No puede asignar un nuevo objeto a una referencia. Lo que está sucediendo aquí es que se llama operador = de Base y el objeto subyacente sigue siendo DerivedA y no DerivadoB.

+2

Todos los días siempre hay algo que aprender. – Luca

+0

No estoy seguro de que esto sea correcto en realidad. El operador = no está definido en Base, por lo que no hay nada que llamar realmente, aparte de la implementación predeterminada de C++ de operator =. Creo que lo que está sucediendo aquí es lo que @MichaelKrelin respondió a continuación. – Rafid

+0

@Rafid Como escribió, existe la implementación predeterminada de operator =. La implementación predeterminada no es virtual y el tipo de base es Base, por lo que se llama Base :: operator =(). La respuesta de Michael también es correcta. Las dos respuestas no se contradicen entre sí. – selalerer

Cuestiones relacionadas