Respuestas:
De la función virtual de Wikipedia ...
En la programación orientada a objetos, en lenguajes como C ++ y Object Pascal, una función virtual o método virtual es una función o método heredable y reemplazable para el cual se facilita el despacho dinámico. Este concepto es una parte importante de la porción de polimorfismo (tiempo de ejecución) de la programación orientada a objetos (OOP). En resumen, una función virtual define una función objetivo que se ejecutará, pero el objetivo puede no ser conocido en el momento de la compilación.
A diferencia de una función no virtual, cuando se anula una función virtual, la versión más derivada se usa en todos los niveles de la jerarquía de clases, en lugar de solo el nivel en el que se creó. Por lo tanto, si un método de la clase base llama a un método virtual, se utilizará la versión definida en la clase derivada en lugar de la versión definida en la clase base.
Esto contrasta con las funciones no virtuales, que aún pueden anularse en una clase derivada, pero la versión "nueva" solo será utilizada por la clase derivada y por debajo, pero no cambiará en absoluto la funcionalidad de la clase base.
mientras..
Una función virtual pura o un método virtual puro es una función virtual que una clase derivada debe implementar si la clase derivada no es abstracta.
Cuando existe un método virtual puro, la clase es "abstracta" y no se puede instanciar por sí sola. En su lugar, se debe utilizar una clase derivada que implemente los métodos virtuales puros. Un virtual puro no está definido en la clase base en absoluto, por lo que una clase derivada debe definirlo, o esa clase derivada también es abstracta y no puede ser instanciada. Solo se puede crear una instancia de una clase que no tenga métodos abstractos.
Un virtual proporciona una forma de anular la funcionalidad de la clase base, y un virtual puro lo requiere .
pure
palabra clave, pero que Bell Labs estaba a punto de hacer un lanzamiento importante de C ++, y su gerente no lo permitiría en esa etapa tardía. Agregar palabras clave es un gran problema.
Me gustaría comentar sobre la definición de Wikipedia de virtual, como lo repiten varios aquí. [En el momento en que se escribió esta respuesta,] Wikipedia definió un método virtual como uno que se puede anular en subclases. [Afortunadamente, Wikipedia se ha editado desde entonces, y ahora lo explica correctamente.] Eso es incorrecto: cualquier método, no solo los virtuales, puede anularse en subclases. Lo que hace virtual es darle polimorfismo, es decir, la capacidad de seleccionar en tiempo de ejecución la anulación más derivada de un método .
Considere el siguiente código:
#include <iostream>
using namespace std;
class Base {
public:
void NonVirtual() {
cout << "Base NonVirtual called.\n";
}
virtual void Virtual() {
cout << "Base Virtual called.\n";
}
};
class Derived : public Base {
public:
void NonVirtual() {
cout << "Derived NonVirtual called.\n";
}
void Virtual() {
cout << "Derived Virtual called.\n";
}
};
int main() {
Base* bBase = new Base();
Base* bDerived = new Derived();
bBase->NonVirtual();
bBase->Virtual();
bDerived->NonVirtual();
bDerived->Virtual();
}
¿Cuál es la salida de este programa?
Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.
Derivado anula todos los métodos de Base: no solo el virtual, sino también el no virtual.
Vemos que cuando tiene un puntero base a derivado (bDerived), llamar a NonVirtual llama a la implementación de la clase Base. Esto se resuelve en tiempo de compilación: el compilador ve que bDerived es una Base *, que NonVirtual no es virtual, por lo que hace la resolución en la clase Base.
Sin embargo, llamar a Virtual llama a la implementación de la clase Derivada. Debido a la palabra clave virtual, la selección del método ocurre en tiempo de ejecución , no en tiempo de compilación. Lo que sucede aquí en tiempo de compilación es que el compilador ve que se trata de una Base *, y que está llamando a un método virtual, por lo que inserta una llamada a la tabla vtable en lugar de la clase Base. Esta vtable se instancia en tiempo de ejecución, de ahí la resolución del tiempo de ejecución a la anulación más derivada.
Espero que esto no haya sido demasiado confuso. En resumen, cualquier método puede anularse, pero solo los métodos virtuales le dan polimorfismo, es decir, la selección en tiempo de ejecución de la anulación más derivada. En la práctica, sin embargo, anular un método no virtual se considera una mala práctica y rara vez se usa, por lo que muchas personas (incluido quien escribió ese artículo de Wikipedia) piensan que solo los métodos virtuales pueden anularse.
Derived*
con las mismas llamadas de función para conducir el punto a casa. De lo contrario, gran respuesta
La palabra clave virtual le da a C ++ su capacidad de soportar el polimorfismo. Cuando tiene un puntero a un objeto de alguna clase como:
class Animal
{
public:
virtual int GetNumberOfLegs() = 0;
};
class Duck : public Animal
{
public:
int GetNumberOfLegs() { return 2; }
};
class Horse : public Animal
{
public:
int GetNumberOfLegs() { return 4; }
};
void SomeFunction(Animal * pAnimal)
{
cout << pAnimal->GetNumberOfLegs();
}
En este ejemplo (tonto), la función GetNumberOfLegs () devuelve el número apropiado en función de la clase del objeto para el que se solicita.
Ahora, considere la función 'SomeFunction'. No le importa qué tipo de objeto animal se le pase, siempre y cuando se derive de Animal. El compilador lanzará automáticamente cualquier clase derivada de un animal a un animal, ya que es una clase base.
Si hacemos esto:
Duck d;
SomeFunction(&d);
produciría '2'. Si hacemos esto:
Horse h;
SomeFunction(&h);
produciría '4'. No podemos hacer esto:
Animal a;
SomeFunction(&a);
porque no se compilará debido a que la función virtual GetNumberOfLegs () es pura, lo que significa que debe implementarse derivando clases (subclases).
Las funciones virtuales puras se utilizan principalmente para definir:
a) clases abstractas
Estas son clases base donde debe derivar de ellas y luego implementar las funciones virtuales puras.
b) interfaces
Estas son clases 'vacías' donde todas las funciones son puramente virtuales y, por lo tanto, debe derivar y luego implementar todas las funciones.
En una clase C ++, virtual es la palabra clave que designa que, un método puede ser anulado (es decir, implementado por) una subclase. Por ejemplo:
class Shape
{
public:
Shape();
virtual ~Shape();
std::string getName() // not overridable
{
return m_name;
}
void setName( const std::string& name ) // not overridable
{
m_name = name;
}
protected:
virtual void initShape() // overridable
{
setName("Generic Shape");
}
private:
std::string m_name;
};
En este caso, una subclase puede anular la función initShape para realizar un trabajo especializado:
class Square : public Shape
{
public:
Square();
virtual ~Square();
protected:
virtual void initShape() // override the Shape::initShape function
{
setName("Square");
}
}
El término virtual puro se refiere a funciones virtuales que deben ser implementadas por una subclase y que la clase base no ha implementado. Usted designa un método como virtual puro utilizando la palabra clave virtual y agregando a = 0 al final de la declaración del método.
Entonces, si quisieras hacer Shape :: initShape puramente virtual, harías lo siguiente:
class Shape
{
...
virtual void initShape() = 0; // pure virtual method
...
};
Al agregar un método virtual puro a su clase, la convierte en una clase base abstracta que es muy útil para separar las interfaces de la implementación.
m_name
. ¿Qué significa m_
eso?
"Virtual" significa que el método puede ser anulado en subclases, pero tiene una implementación directamente invocable en la clase base. "Virtual puro" significa que es un método virtual sin implementación directamente invocable. Dicho método debe anularse al menos una vez en la jerarquía de herencia: si una clase tiene algún método virtual no implementado, los objetos de esa clase no se pueden construir y la compilación fallará.
@quark señala que los métodos virtuales puros pueden tener una implementación, pero como los métodos virtuales puros deben anularse, la implementación predeterminada no se puede llamar directamente. Aquí hay un ejemplo de un método virtual puro con un valor predeterminado:
#include <cstdio>
class A {
public:
virtual void Hello() = 0;
};
void A::Hello() {
printf("A::Hello\n");
}
class B : public A {
public:
void Hello() {
printf("B::Hello\n");
A::Hello();
}
};
int main() {
/* Prints:
B::Hello
A::Hello
*/
B b;
b.Hello();
return 0;
}
Según los comentarios, si la compilación fallará o no es específica del compilador. En GCC 4.3.3 al menos, no compilará:
class A {
public:
virtual void Hello() = 0;
};
int main()
{
A a;
return 0;
}
Salida:
$ g++ -c virt.cpp
virt.cpp: In function ‘int main()’:
virt.cpp:8: error: cannot declare variable ‘a’ to be of abstract type ‘A’
virt.cpp:1: note: because the following virtual functions are pure within ‘A’:
virt.cpp:3: note: virtual void A::Hello()
¿Cómo funciona la palabra clave virtual?
Suponga que el hombre es una clase base, el indio se deriva del hombre.
Class Man
{
public:
virtual void do_work()
{}
}
Class Indian : public Man
{
public:
void do_work()
{}
}
Declarar do_work () como virtual simplemente significa: qué do_work () llamar se determinará SOLO en tiempo de ejecución.
Supongamos que sí
Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.
Si no se usa virtual, el compilador determina estáticamente o está vinculado estáticamente, dependiendo de qué objeto está llamando. Entonces, si un objeto de Man llama a do_work (), el do_work () de Man se llama INCLUSO AUNQUE SEÑALA A UN OBJETO INDIO
Creo que la respuesta más votada es engañosa: cualquier método, sea virtual o no, puede tener una implementación anulada en la clase derivada. Con referencia específica a C ++, la diferencia correcta es el enlace en tiempo de ejecución (cuando se usa virtual) y el tiempo de compilación (cuando no se usa virtual pero se anula un método y un puntero base apunta a un objeto derivado) enlace de funciones asociadas.
Parece haber otro comentario engañoso que dice:
"Justin, 'puro virtual' es solo un término (no una palabra clave, vea mi respuesta a continuación) usado para significar" esta clase básica no puede implementar esta función ".
¡ESTO ESTÁ MAL! ¡Las funciones puramente virtuales también pueden tener un cuerpo Y PUEDEN SER IMPLEMENTADAS! ¡La verdad es que una función virtual pura de una clase abstracta se puede llamar estáticamente! Dos autores muy buenos son Bjarne Stroustrup y Stan Lippman ... porque escribieron el idioma.
Una función virtual es una función miembro que se declara en una clase base y que se redefine por clase derivada. Las funciones virtuales son jerárquicas en orden de herencia. Cuando una clase derivada no anula una función virtual, se utiliza la función definida dentro de su clase base.
Una función virtual pura es aquella que no contiene ninguna definición relativa a la clase base. No tiene implementación en la clase base. Cualquier clase derivada debe anular esta función.
Simula, C ++ y C #, que utilizan el enlace de método estático de forma predeterminada, el programador puede especificar que determinados métodos deben usar el enlace dinámico etiquetándolos como virtuales. El enlace dinámico de métodos es fundamental para la programación orientada a objetos.
La programación orientada a objetos requiere tres conceptos fundamentales: encapsulación, herencia y enlace dinámico de métodos.
La encapsulación permite ocultar los detalles de implementación de una abstracción detrás de una interfaz simple.
La herencia permite que una nueva abstracción se defina como una extensión o refinamiento de alguna abstracción existente, obteniendo algunas o todas sus características automáticamente.
El enlace de método dinámico permite que la nueva abstracción muestre su nuevo comportamiento incluso cuando se usa en un contexto que espera la antigua abstracción.
Los métodos virtuales PUEDEN anularse derivando clases, pero necesitan una implementación en la clase base (la que se anulará)
Los métodos virtuales puros no tienen implementación de la clase base. Deben definirse por clases derivadas. (Por lo tanto, anular técnicamente no es el término correcto, porque no hay nada que anular).
Virtual corresponde al comportamiento predeterminado de Java, cuando la clase derivada anula un método de la clase base.
Los métodos virtuales puros corresponden al comportamiento de los métodos abstractos dentro de las clases abstractas. Y una clase que solo contiene constantes y métodos virtuales puros sería el colgante cpp de una interfaz.
Función virtual pura
prueba este código
#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{
public:
virtual void sayHellow()=0;
};
class anotherClass:aClassWithPureVirtualFunction
{
public:
void sayHellow()
{
cout<<"hellow World";
}
};
int main()
{
//aClassWithPureVirtualFunction virtualObject;
/*
This not possible to create object of a class that contain pure virtual function
*/
anotherClass object;
object.sayHellow();
}
En la clase anotherClass elimine la función sayHellow y ejecute el código. ¡obtendrá un error! Porque cuando una clase contiene una función virtual pura, no se puede crear ningún objeto a partir de esa clase y se hereda, entonces su clase derivada debe implementar esa función.
Función virtual
prueba con otro código
#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{
public:
virtual void sayHellow()
{
cout<<"from base\n";
}
};
class anotherClass:public aClassWithPureVirtualFunction
{
public:
void sayHellow()
{
cout<<"from derived \n";
}
};
int main()
{
aClassWithPureVirtualFunction *baseObject=new aClassWithPureVirtualFunction;
baseObject->sayHellow();///call base one
baseObject=new anotherClass;
baseObject->sayHellow();////call the derived one!
}
Aquí la función sayHellow está marcada como virtual en la clase base. Dice el compilador que intenta buscar la función en la clase derivada e implementa la función. Si no se encuentra, ejecute la base. Gracias
"Una función virtual o método virtual es una función o método cuyo comportamiento puede ser anulado dentro de una clase heredada por una función con la misma firma" - wikipedia
Esta no es una buena explicación para las funciones virtuales. Porque, incluso si un miembro no es virtual, las clases heredadas pueden anularlo. Puedes intentar verlo tú mismo.
La diferencia se muestra cuando una función toma una clase base como parámetro. Cuando da una clase heredada como entrada, esa función usa la implementación de la clase base de la función anulada. Sin embargo, si esa función es virtual, utiliza la que se implementa en la clase derivada.
Las funciones virtuales deben tener una definición en la clase base y también en la clase derivada, pero no es necesaria, por ejemplo, la función ToString () o toString () es una Virtual, por lo que puede proporcionar su propia implementación al anularla en las clases definidas por el usuario.
Las funciones virtuales se declaran y definen en la clase normal.
La función virtual pura debe declararse terminando con "= 0" y solo puede declararse en clase abstracta.
Una clase abstracta que tiene una (s) función (es) virtual (s) pura (s) no puede tener una (s) definición (es) de esa función virtual pura, por lo que implica que la implementación debe proporcionarse en la (s) clase (s) que derivan de esa clase abstracta.