online - pure virtual function c++
C++ Virtual/Pure Virtual Explicado (13)
¿Qué significa exactamente si una función se define como virtual y es lo mismo que virtual puro?
"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 intentarlo y verlo tú mismo.
La diferencia se muestra a sí misma cuando una función toma una clase base como parámetro. Cuando asigna una clase heredada como entrada, esa función utiliza 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.
"Virtual" significa que el método se puede invalidar en las subclases, pero tiene una implementación directamente ejecutable en la clase base. "Puro virtual" significa que es un método virtual sin una implementación directamente ejecutable. Dicho método debe anularse al menos una vez en la jerarquía de herencia: si una clase tiene algún método virtual sin implementar, los objetos de esa clase no pueden construirse y la compilación fallará.
@quark señala que los métodos puramente virtuales pueden tener una implementación, pero como los métodos puramente virtuales deben ser anulados, la implementación predeterminada no puede ser llamada 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ífico 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?
Supongamos 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: a qué do_work () llamar se determinará SOLAMENTE en tiempo de ejecución.
Supongamos que lo hago,
Man *man;
man = new Indian();
man->do_work(); // Indian''s do work is only called.
Si no se usa virtual, el compilador determina de forma estática o estáticamente el mismo, dependiendo de qué objeto está llamando. Por lo tanto, si un objeto de Man llama a do_work (), el do_work () de Man se llama AUNQUE PONGA A UN OBJETO INDIO
Creo que la respuesta más votada es engañosa: cualquier método, ya sea virtual o no, puede tener una implementación anulada en la clase derivada. Con una referencia específica a C ++, la diferencia correcta es el tiempo de ejecución (cuando se usa virtual) y el tiempo de compilación (cuando no se usa virtual pero un método está anulado y un puntero de base apunta a un objeto derivado) vinculante de funciones asociadas.
Parece que hay otro comentario engañoso que dice:
"Justin, ''virtual puro'' es solo un término (no una palabra clave, vea mi respuesta a continuación) que significa" la clase base no puede implementar esta función ".
¡ESTO ESTÁ MAL! Las funciones puramente virtuales también pueden tener un cuerpo ¡Y PUEDEN IMPLEMENTARSE! ¡La verdad es que la función virtual pura de una clase abstracta puede llamarse estáticamente! Dos autores muy buenos son Bjarne Stroustrup y Stan Lippman ... porque escribieron el lenguaje.
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 envío 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 de destino que se ejecutará, pero es posible que el objetivo no se conozca en el momento de la compilación.
A diferencia de una función no virtual, cuando se invalida 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 ser anuladas en una clase derivada, pero la versión "nueva" solo será utilizada por la clase derivada y las siguientes, pero no cambiará la funcionalidad de la clase base en absoluto.
mientras..
Una función virtual pura o un método virtual puro es una función virtual que debe ser implementada por una clase derivada si la clase derivada no es abstracta.
Cuando existe un método virtual puro, la clase es "abstracta" y no puede ser instanciada por sí misma. En su lugar, se debe utilizar una clase derivada que implemente los métodos virtuales puros. Una clase virtual pura no está definida en absoluto en la clase base, por lo que una clase derivada debe definirla, o esa clase derivada también es abstracta y no puede ser instanciada. Sólo se puede crear una instancia de una clase que no tiene métodos abstractos.
Un virtual proporciona una forma de anular la funcionalidad de la clase base, y un virtual virtual lo requiere .
En la programación orientada a objetos, una función virtual o método virtual es una función o método cuyo comportamiento puede ser anulado dentro de una clase hereditaria por una función con la misma firma para proporcionar el comportamiento polimórfico.
En palabras más simples, supongamos que hay una clase Base que tiene un nombre de función print () y que hay otra clase Child que se hereda de la clase Base y también tiene un nombre de función print () Ahora, si la función de la clase Base, es decir, Base :: print () no es virtual, la función de la clase secundaria es decir, Child :: print () no anulará la función de la clase Base durante el tiempo de ejecución. Y si Base :: print () se convierte en virtual, entonces la función Child :: print () anulará la función de clase Base. Los ejemplos relacionados con estos se muestran en las siguientes secciones.
En una clase de 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 algún 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 las funciones virtuales que deben ser implementadas por una subclase y no han sido implementadas por la clase base. Usted designa un método como virtual puro usando la palabra clave virtual y agregando un = 0 al final de la declaración del método.
Entonces, si quisieras hacer que Shape :: initShape sea 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, hace de la clase una clase base abstracta que es muy útil para separar interfaces de implementación.
La palabra clave virtual le da a C ++ su capacidad para soportar el polimorfismo. Cuando tienes 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 que se solicita.
Ahora, considere la función ''SomeFunction''. No importa qué tipo de objeto animal se le pase, siempre que 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);
saldría ''2''. Si hacemos esto:
Horse h;
SomeFunction(&h);
saldrí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 en las que 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, tiene que derivar y luego implementar todas las funciones.
Los métodos virtuales se pueden invalidar derivando clases, pero necesitan una implementación en la clase base (la que se anulará)
Los métodos virtuales puros no tienen implementación la clase base. Necesitan ser definidos por clases derivadas. (Por lo tanto, técnicamente anulado no es el término correcto, porque no hay nada que anular).
Virtual corresponde al comportamiento java predeterminado, 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.
Me gustaría comentar sobre la definición de virtual de Wikipedia, tal como se repite aquí. [En el momento en que se escribió esta respuesta,] Wikipedia definió un método virtual como uno que se puede anular en las subclases. [Afortunadamente, la Wikipedia ha sido editada desde entonces, y ahora explica esto correctamente.] Eso es incorrecto: cualquier método, no solo los virtuales, puede ser anulado en las 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 a derivado base (bDerived), llamar a la implementación de la clase base llama a NonVirtual. 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 esto es una Base *, y que está llamando a un método virtual, por lo que inserta una llamada a vtable en lugar de la clase Base. Esta vtable se crea una instancia en tiempo de ejecución, por lo tanto, la resolución en tiempo de ejecución para la anulación más derivada.
Espero que esto no fuera demasiado confuso. En resumen, cualquier método puede ser anulado, 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 el que escribió el artículo de Wikipedia) piensan que solo se pueden anular los métodos virtuales.
Simula, C ++ y C #, que utilizan el enlace de método estático de forma predeterminada, el programador puede especificar que los métodos particulares deben usar el enlace dinámico etiquetándolos como virtuales. El enlace dinámico del método es fundamental para la programación orientada a objetos.
La programación orientada a objetos requiere tres conceptos fundamentales: encapsulación, herencia y unión dinámica 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 definir una nueva abstracción como una extensión o refinamiento de alguna abstracción existente, obteniendo algunas o todas sus características automáticamente.
El enlace dinámico del método permite que la nueva abstracción muestre su nuevo comportamiento incluso cuando se usa en un contexto que espera la abstracción antigua.
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 de esa clase y se hereda, entonces su clase derivada debe implementar esa función.
Funcion virtual
prueba 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 se marca como virtual en la clase base. Dice que 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 es una función miembro que se declara en una clase base y se redefine por la 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 una definición relativa a la clase base. No tiene implementación en la clase base. Cualquier clase derivada debe anular esta función.
Las funciones virtuales deben tener una definición en la clase base y también en la clase derivada, pero no son necesarias, por ejemplo, ToString () o la función 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 están declaradas y definidas en la clase normal.
La función virtual pura debe declararse terminando con "= 0" y solo se puede declarar en clase abstracta.
Una clase abstracta que tiene una (s) función (es) virtual (es) pura (s) no puede (n) tener una definición (es) de esa función virtual pura, por lo que implica que la implementación debe proporcionarse en la (s) clase (s) derivada (s) de esa clase abstracta.