En C ++, ¿es una función virtual automáticamente si anula una función virtual?

StackOverflow https://stackoverflow.com/questions/1404797

  •  05-07-2019
  •  | 
  •  

Pregunta

Supongo que si foo se declara en la clase D , pero no se marca como virtual, el siguiente código llamará a la implementación de foo en D (independientemente del tipo dinámico de d ).

D& d = ...;
d.foo();

Sin embargo, en el siguiente programa, ese no es el caso. ¿Alguien puede explicar esto? ¿Es un método automáticamente virtual si anula una función virtual?

#include <iostream>

using namespace std;

class C {
public:
        virtual void foo() { cout << "C" << endl; }
};

class D : public C {
public:
        void foo() { cout << "D" << endl; }
};

class E : public D {
public:
        void foo() { cout << "E" << endl; }
};

int main(int argc, char **argv)
{
        E& e = *new E;
        D& d = *static_cast<D*>(&e);
        d.foo();
        return 0;
}

El resultado del programa anterior es:

E
¿Fue útil?

Solución

El estándar 10.3.2 (class.virtual) dice:

  

Si una función miembro virtual vf se declara en una clase Base y en una clase Derivada, derivada directa o indirectamente de Base, se declara una función miembro vf con el mismo nombre y la misma lista de parámetros que Base :: vf, entonces Derivada :: vf también es virtual (esté o no declarado) y anula *

     

[Nota al pie: una función con el mismo nombre pero una lista de parámetros diferente (cláusula sobre) como una función virtual no es necesariamente virtual y no se anula. El uso del especificador virtual en la declaración de una función de anulación es legal pero redundante (tiene una semántica vacía). El control de acceso (cláusula class.access) no se considera para determinar la anulación. --- terminar foonote]

Otros consejos

La respuesta rápida puede ser no, pero la respuesta correcta es

C ++ no sabe sobre el ocultamiento de funciones, por lo que anula la función virtual sin marcas de palabras clave virtuales que también funcionen virtuales.

No estás creando ninguna copia del objeto de e y poniéndola en d. Así que d.foo () sigue el comportamiento polimórfico normal y llama al método de clase derivado. Un método que se declara como virtual en la clase base también se vuelve automáticamente virtual en la clase derivada.

La salida (" E ") se comporta exactamente como uno esperaría que se comportara.

La razón: El tipo dinámico (es decir, el tiempo de ejecución) de esa referencia es E. Está realizando una actualización estática a D, pero eso no cambia el tipo real del objeto, por supuesto.

Esa es la idea detrás de los métodos virtuales y los envíos dinámicos: ve el comportamiento del tipo que estaba creando una instancia de E, en este caso.

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