¿Casos de uso de funciones virtuales puras con body?


Recientemente supe que en C++ las funciones virtuales puras pueden tener opcionalmente un cuerpo.

¿Cuáles son los casos de uso del mundo real para tales funciones?

Author: missingfaktor, 2010-04-09

7 answers

El clásico es un destructor virtual puro:

class abstract {
  public: 
    virtual ~abstract() = 0;
};

abstract::~abstract() {}

Lo haces puro porque no hay nada más para hacerlo, y quieres que la clase sea abstracta, pero tienes que proporcionar una implementación sin embargo, porque los destructores de las clases derivadas llaman a la tuya explícitamente. Sí, lo sé, un ejemplo de libro de texto bastante tonto, pero como tal es un clásico. Debe haber sido en la primera edición de El Lenguaje de Programación C++ .

De todos modos, no puedo recordar nunca realmente necesita la capacidad de implementar una función virtual pura. A mí me parece que la única razón por la que esta característica está allí es porque habría tenido que ser explícitamente rechazada y Stroustrup no vio una razón para eso.

Si alguna vez sientes que necesitas esta función, probablemente estés en el camino equivocado con tu diseño.

 36
Author: sbi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 17:49:55

Las funciones virtuales puras con o sin un cuerpo simplemente significan que los tipos derivados deben proporcionar su propia implementación.

Los cuerpos de función virtuales puros en la clase base son útiles si sus clases derivadas quieren llamar a su implementación de clase base.

 32
Author: Brian R. Bondy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 16:54:15

Una razón por la que una clase base abstracta (con una función virtual pura) podría proporcionar una implementación para una función virtual pura que declara es permitir que las clases derivadas tengan un 'predeterminado' fácil que puedan elegir usar. No hay mucha ventaja en esto sobre una función virtual normal que pueda ser opcionalmente anulada - de hecho, la única diferencia real es que estás forzando a la clase derivada a ser explícita sobre el uso de la clase base' predeterminada' aplicación:

class foo {
public:
    virtual int interface();
};

int foo::interface() 
{
    printf( "default foo::interface() called\n");
    return 0;
};


class pure_foo {
public:
    virtual int interface() = 0;
};

int pure_foo::interface()
{
    printf( "default pure_foo::interface() called\n");
    return 42;
}

//------------------------------------

class foobar : public foo {
    // no need to override to get default behavior
};

class foobar2 : public pure_foo {
public:
    // need to be explicit about the override, even to get default behavior
    virtual int interface();
};

int foobar2::interface()
{
    // foobar is lazy; it'll just use pure_foo's default
    return pure_foo::interface();
}

No estoy seguro de que haya un gran beneficio - tal vez en los casos en que un diseño comenzó con una clase abstracta, luego con el tiempo descubrió que muchas de las clases concretas derivadas estaban implementando el mismo comportamiento, por lo que decidieron mover ese comportamiento a una implementación de clase base para la función virtual pura.

Supongo que también podría ser razonable poner un comportamiento común en la implementación de la clase base de la función virtual pura que el derivado se puede esperar que las clases modifiquen / mejoren / aumenten.

 16
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 17:30:51

Un caso de uso es llamar a la función virtual pura desde el constructor o el destructor de la clase.

 8
Author: shoosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 16:54:38

El todopoderoso Herb Sutter, ex presidente del comité de estándares de C++, dio 3 escenarios donde podría considerar proporcionar implementaciones para métodos virtuales puros.

Tengo que decir que personalmente – no encuentro ninguno de ellos convincente, y en general consideran que este es uno de C++'s verrugas semánticas. Parece que C++ se sale de su camino para construir y separar vtables abstractas-padre, que los expone brevemente solo durante la construcción/destrucción del hijo, y entonces los expertos comunitarios recomiendan unánimementeno utilizarlos nunca .

 7
Author: Ofek Shilon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-14 05:57:33

La única diferencia entre la función virtual con el cuerpo y la función virtual pura con el cuerpo es que la existencia del segundo previene la instanciación. No se puede marcar resumen de clase en c++.

 4
Author: Andrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 16:54:51

Esta pregunta puede ser realmente confusa cuando se aprende OOD y C++. Personalmente, una cosa que venía constantemente en mi cabeza era algo como: Si necesitaba una función Virtual Pura para tener también una implementación, entonces, ¿por qué hacerla "Pura" en primer lugar ? ¿Por qué no dejarlo solo "Virtual" y haber derivado tanto beneficio como anulación de la implementación base ?

La confusión llega al hecho de que muchos desarrolladores consideran el no cuerpo / implementación como el objetivo principal / beneficio de definir una función virtual pura. ¡Esto no es verdad! La ausencia de cuerpo es en la mayoría de los casos una consecuencia lógica de tener una función virtual pura. El principal beneficio de tener una función virtual pura es DEFINIR UN CONTRATO! Al definir una función virtual pura, desea FORZAR a cada derivado a proporcionar SIEMPRE su PROPIA IMPLEMENTACIÓN de la función. Este "aspecto de CONTRATO" es muy importante, especialmente si está desarrollando algo como una API pública. Hacer que la función solo sea virtual no es tan suficiente porque los derivados ya no están obligados a proporcionar su propia implementación, por lo tanto, puede perder el aspecto del contrato (esto puede ser limitante en el caso de una API pública). Como se suele decir : "Las funciones virtuales PUEDEN ser anuladas, las funciones virtuales puras DEBEN ser anuladas." Y en la mayoría de los casos, los contratos son conceptos abstractos por lo que no tiene sentido que las funciones virtuales puras correspondientes tengan alguna implementación.

Pero a veces, y porque la vida es rara, puede que quieren establecer un contrato fuerte entre los derivados y también quieren que de alguna manera se beneficien de alguna implementación por defecto al tiempo que especifican su propio comportamiento para el contrato. Incluso si la mayoría de los autores de libros recomiendan evitar meterse en estas situaciones, el lenguaje necesario para proporcionar una red de seguridad para evitar lo peor! Una simple función virtual no sería suficiente ya que podría haber riesgo de escapar del contrato. Así que la solución que C++ proporcionó fue permitir que las funciones virtuales puras también ser capaz de proporcionar una implementación predeterminada.

El artículo de Sutter citado anteriormente da casos de uso interesantes de tener funciones virtuales puras con body.

 3
Author: Elvis Attro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-05 13:36:17