2012-06-17 12 views
37

Asumamos este escenario en Visual C++ 2010:métodos no virtuales Sustitución

#include <iostream> 
#include <conio.h> 

using namespace std; 

class Base 
{ 
public: 
    int b; 
    void Display() 
    { 
     cout<<"Base: Non-virtual display."<<endl; 
    }; 
    virtual void vDisplay() 
    { 
     cout<<"Base: Virtual display."<<endl; 
    }; 
}; 

class Derived : public Base 
{ 
public: 
    int d; 
    void Display() 
    { 
     cout<<"Derived: Non-virtual display."<<endl; 
    }; 
    virtual void vDisplay() 
    { 
     cout<<"Derived: Virtual display."<<endl; 
    }; 
}; 

int main() 
{ 
    Base ba; 
    Derived de; 

    ba.Display(); 
    ba.vDisplay(); 
    de.Display(); 
    de.vDisplay(); 

    _getch(); 
    return 0; 
}; 

En teoría, la salida de esta pequeña aplicación debe ser:

  • Base: pantalla no virtual.
  • Base: pantalla virtual.
  • Base: Pantalla no virtual.
  • Derivado: Pantalla virtual.

porque el Método de visualización de la clase Base no es un método virtual, por lo que la clase Derivada no debería poder sobrescribirlo. ¿Derecha?

El problema es que cuando ejecuto la aplicación, se imprime la siguiente:

  • Base: pantalla no virtual.
  • Base: pantalla virtual.
  • Derivado: Visualización no virtual.
  • Derivado: Pantalla virtual.

Entonces o no entendí el concepto de métodos virtuales o algo extraño sucede en Visual C++.

¿Podría alguien ayudarme con una explicación?

+0

tendría absolutamente __Base: visualización no virtual .__ al cambiar su línea a 'de.Base :: Display()'. –

Respuesta

50

Sí, estás malentendiendo un poco.

El método del mismo nombre en la clase derivada ocultará el método principal en este caso. Imagine que si este no fuera el caso, tratar de crear un método con el mismo nombre que un método no virtual de clase base arrojaría un error. Está permitido y no es un problema, y ​​si llama al método directamente como lo ha hecho, se llamará bien.

Pero, al ser no virtual, no se utilizarán mecanismos de búsqueda de métodos C++ que permitan el polimorfismo. Entonces, por ejemplo, si creó una instancia de su clase derivada pero llamó a su método 'Pantalla' mediante un puntero a la clase base, se llamará al método base, mientras que para 'vDisplay' se invocará el método derivado.

Por ejemplo, trate de añadir estas líneas:

Base *b = &ba; 
b->Display(); 
b->vDisplay(); 
b = &de; 
b->Display(); 
b->vDisplay(); 

... y observar la salida como se esperaba:

Base: pantalla no virtual.
Base: pantalla virtual.
Base: pantalla no virtual.
Derivado: Visualización virtual.

+0

Hola @ sje397, gracias por su respuesta. ¿Puedes escribir un ejemplo de cómo llamar al método, como dijiste, mediante un puntero a la clase base? ¡Gracias! –

+0

@Leif Lazar: hecho. – sje397

+0

también como dije, TAMBIÉN puede llamar al método base (no virtual) desde la instancia derivada, usando la sintaxis de resolución del alcance. –

3

Sí se han entendido un poco:

funciones virtuales puras:

virtual void fun1()=0 -> debe ser anulado en la clase derivada

funciones virtuales:

virtual void fun2() -> puede anularse

funciones normales:

void fun3() -> no anulan los que

Con el fin de lograr el polimorfismo en tiempo de ejecución se debe redefinir las funciones virtuales en C++

0

yo creo que puede ser también mejor a la vista en el contexto de enlace estático vs dinámico.

Si el método no es virtual (ya es predeterminado en C++ a diferencia de Java), el método se une a su llamador en tiempo de compilación, que es imposible conocer el objeto real que se señalará en el tiempo de ejecución. Entonces, el tipo de variable es lo único que importa, que es la 'Base'.

Cuestiones relacionadas