La pregunta en el tema sugiere una confusión bastante común. La confusión es bastante común, que las preguntas frecuentes de C ++ abogaron contra el uso de virtuales privados, durante mucho tiempo, porque la confusión parecía ser algo malo.
Entonces, para deshacerse de la confusión primero: Sí, las funciones virtuales privadas pueden anularse en las clases derivadas. Los métodos de clases derivadas no pueden llamar a funciones virtuales desde la clase base, pero pueden proporcionar su propia implementación para ellas. 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 al respecto en su artículo "Virtualidad" .
Sin embargo, hay una cosa más interesante en el código que presentó, que merece más atención, en mi opinión. La interfaz pública consta de un conjunto de funciones no virtuales sobrecargadas y esas funciones llaman funciones virtuales no públicas, no sobrecargadas. Como es habitual en el mundo de C ++, es un idioma, tiene un nombre y, por supuesto, es útil. El nombre es (¡sorpresa, sorpresa!)
"Públicos no virtuales sobrecargados Llamadas virtuales no sobrecargadas protegidas"
Ayuda a gestionar adecuadamente la regla de ocultación . Puede leer más sobre esto aquí , pero trataré de explicarlo en breve.
Imagine que las funciones virtuales de la Engine
clase también son su interfaz y es un conjunto de funciones sobrecargadas que no es puramente virtual. Si fueran puramente virtuales, todavía se podría encontrar el mismo problema, como se describe a continuación, pero más abajo 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 supongamos que desea crear una clase derivada y necesita proporcionar una nueva implementación solo para el método, que toma dos entradas 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 olvidó poner la declaración de uso en la clase derivada (o redefinir la segunda sobrecarga), podría meterse en problemas en el siguiente escenario.
MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);
Si no evitaste la ocultación de los Engine
miembros, la declaración:
myV8->SetState(5, true);
llamaría void SetState( int var, int val )
desde la clase derivada, convirtiendo true
a int
.
Si la interfaz no es virtual y la implementación virtual no es pública, como en su ejemplo, el autor de la clase derivada tiene un problema menos en el que pensar y simplemente puede escribir
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val ) {/*new implementation*/}
};