La pregunta en el tema sugiere una confusión bastante común. La confusión es bastante común, que C++ FAQ abogó contra el uso de virtuales privadas, durante mucho tiempo, porque la confusión parecía ser algo malo.
Para deshacerse primero de la confusión: Sí, las funciones privadas virtuales pueden anularse en las clases derivadas. Los métodos de clases derivadas no pueden invocar funciones virtuales desde la clase base, pero pueden proporcionarles su propia implementación. Según Herb Sutter, tener una interfaz pública no virtual en la clase base y una implementación privada que se puede personalizar en las clases derivadas, permite una mejor "separación de la especificación de la interfaz de la especificación del comportamiento personalizable de la implementación". Puede leer más sobre esto en su artículo "Virtuality".
Sin embargo, hay una cosa más interesante en el código que usted presentó, que merece más atención, en mi opinión. La interfaz pública consiste en un conjunto de funciones no virtuales sobrecargadas y esas funciones llaman a funciones virtuales no públicas y no sobrecargadas. Como es habitual en el mundo de C++, es un modismo, tiene un nombre y, por supuesto, es útil. El nombre es (sorpresa, sorpresa!)
"público sobrecargado no Virtuales de llamadas protegidas con sobrecarga no Virtuales"
Ayuda a properly manage the hiding rule. Puede leer más al respecto here, pero trataré de explicarlo en breve.
Imagine que las funciones virtuales de la clase Engine
también son su interfaz y es un conjunto de funciones sobrecargadas que no es puramente virtual. Si fueran virtuales puros, uno podría encontrar el mismo problema, como se describe a continuación, pero inferior en la jerarquía de clases.
class Engine
{
public:
virtual void SetState(int var, bool val) {/*some implementation*/}
virtual void SetState(int var, int val) {/*some implementation*/}
};
Ahora vamos a suponer que desea crear una clase derivada y es necesario proporcionar una nueva aplicación sólo para el método, que toma dos enteros como argumentos.
class MyTurbochargedV8 : public Engine
{
public:
// To prevent SetState(int var, bool val) from the base class,
// from being hidden by the new implementation of the other overload (below),
// you have to put using declaration in the derived class
using Engine::SetState;
void SetState(int var, int val) {/*new implementation*/}
};
Si se olvida de poner la declaración using en la clase derivada (o redefinir el segundo sobrecarga), usted podría tener problemas en el escenario a continuación.
MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);
Si no impidió que la ocultación de los miembros Engine
, la declaración:
myV8->SetState(5, true);
llamarían void SetState(int var, int val)
de la clase derivada, convirtiendo a true
int
.
Si la interfaz no es virtual y la aplicación virtual es que no es pública, como en el ejemplo, los grupos el autor de la clase derivada tiene un problema menos para pensar y simplemente puede escribir
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val) {/*new implementation*/}
};
+1 para "Virtuales no sobrecargados no virtuales con sobrecarga pública no sobrecargados" xD – GabLeRoux
¿por qué la función virtual tiene que ser privada? ¿Puede ser público? – Rich
Me pregunto si las pautas dadas por Herb Sutter en su artículo de "Virtualidad" aún se mantienen hoy en día? – nurabha