c++ - que - ¿Bajo qué circunstancias es ventajoso dar una implementación de una función virtual pura?
polimorfismo puro c++ (6)
En C ++, es legal dar una implementación de una función virtual pura:
class C
{
public:
virtual int f() = 0;
};
int C::f()
{
return 0;
}
¿Por qué querrías hacer esto?
Pregunta relacionada: El C ++ faq lite contiene un ejemplo:
class Funct {
public:
virtual int doit(int x) = 0;
virtual ~Funct() = 0;
};
inline Funct::~Funct() { } // defined even though it''s pure virtual; it''s faster this way; trust me
No entiendo por qué el destructor se declara virtual puro y luego se implementa; y no entiendo el comentario por qué esto debería ser más rápido.
Acabo de descubrir que Herb Sutter respondió la primera parte de esta pregunta en su Gurú de la semana # 31 .
Con respecto a la velocidad del destructor virtual, esto se debe a que el destructor está definido en el archivo cpp y no en el encabezado. Tiene más que ver con el tamaño que con la velocidad. Se explica en detalle en "Diseño de software C ++ a gran escala". Desafortunadamente, no puedo recordar todos los detalles, pero creo que las funciones virtuales en línea se definen varias veces en vtable.
Hay una discusión aquí: ¿son las funciones virtuales en línea realmente un no sentido?
Dia de dia
En lo que respecta a proporcionar una implementación predeterminada para una función miembro declarada en una clase base, la única razón que se me ocurre en este momento es cuando desea proporcionar una implementación predeterminada del comportamiento como una posible opción de implementación para alguien que está especializando la clase base .
El autor de la clase derivada puede elegir usar la implementación predeterminada proporcionada por el autor de la clase base en lugar de agregar su propia implementación especializada.
Este es generalmente el caso en el que las personas se oponen a tener funciones separadas para proporcionar una interfaz y una implementación predeterminada del comportamiento, pero aún desean una separación entre la implementación predeterminada y la interfaz asociada.
Ah, acabo de ver el post de @Martin York que proporciona un ejemplo.
En realidad, Scott Meyers discute esto en su libro "Efectivo C ++". Es el artículo 36 en la 1ª edición.
HTH
aclamaciones,
Los destructores declarados siempre deben implementarse, ya que la implementación los llamará como parte de la destrucción de objetos derivados.
Se pueden implementar otras funciones virtuales puras si proporcionan una funcionalidad común útil pero siempre necesitan ser especializadas. En el caso, las implementaciones de clase típicamente derivadas harán una llamada explícita a la implementación base:
void Derived::f()
{
Base::f();
// Other Derived specific functionality
}
Por lo general, se hace un destructor virtual si necesita hacer un resumen de clase (es decir, evitar que se creen instancias no derivadas) pero la clase no tiene otras funciones que sean naturalmente virtuales. Creo que ''confía en mí es más rápido'' se refiere al hecho de que, como los destructores llamados como parte de la limpieza de objetos derivados no necesitan usar un mecanismo de búsqueda vtable, se puede aprovechar la implementación en línea, a diferencia de las llamadas a funciones virtuales típicas .
Porque se considera mal formado para escribir:
class Funct {
public:
virtual int doit(int x) = 0;
virtual ~Funct() = 0 {};
};
El destructor aún será llamado si usted deriva de esta clase. Declarar todos los métodos puramente virtuales es solo por claridad. Bien podría escribirlo así:
class Funct {
public:
virtual int doit(int x) = 0;
virtual ~Funct() {};
};
La clase seguirá siendo abstracta ya que al menos un método es puramente virtual. El destructor también está en línea.
Si tiene una funcionalidad tan común que la clase derivada puede utilizar. Pero necesitan hacer otro trabajo también.
Así que la clase derivada implementa la función virtual y llama a la versión base subyacente:
class X: public C
{
public:
virtual int f()
{
return C::f() + 1; // I am +1 over my parent.
}
};