A pergunta no tópico sugere uma confusão bastante comum. A confusão é bastante comum, que o C ++ FAQ defendeu contra o uso de virtuais privados, por um longo tempo, porque a confusão parecia ser uma coisa ruim.
Portanto, para se livrar da confusão primeiro: Sim, funções virtuais privadas podem ser substituídas nas classes derivadas. Os métodos de classes derivadas não podem chamar funções virtuais da classe base, mas podem fornecer sua própria implementação para eles. De acordo com Herb Sutter, ter uma interface pública não virtual na classe base e uma implementação privada que pode ser personalizada nas classes derivadas, permite uma melhor "separação da especificação da interface da especificação do comportamento personalizável da implementação". Você pode ler mais sobre isso em seu artigo "Virtualidade" .
Há, no entanto, mais uma coisa interessante no código que você apresentou, que merece mais atenção, na minha opinião. A interface pública consiste em um conjunto de funções não virtuais sobrecarregadas e essas funções chamam funções virtuais não públicas e não sobrecarregadas. Como de costume no mundo C ++, é um idioma, tem um nome e, claro, é útil. O nome é (surpresa, surpresa!)
"Públicos não virtuais sobrecarregados chamam virtuais não sobrecarregados protegidos"
Ajuda a gerenciar adequadamente a regra de ocultação . Você pode ler mais sobre isso aqui , mas tentarei explicar em breve.
Imagine que as funções virtuais da Engine
classe também são sua interface e é um conjunto de funções sobrecarregadas que não é virtual puro. Se fossem virtuais, ainda era possível encontrar o mesmo problema, conforme descrito abaixo, mas menor na hierarquia de classes.
class Engine
{
public:
virtual void SetState( int var, bool val ) {/*some implementation*/}
virtual void SetState( int var, int val ) {/*some implementation*/}
};
Agora vamos assumir que você deseja criar uma classe derivada e precisa fornecer uma nova implementação apenas para o método, que usa duas 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*/}
};
Se você esqueceu de colocar a declaração de uso na classe derivada (ou redefinir a segunda sobrecarga), poderá ter problemas no cenário abaixo.
MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);
Se você não impediu a ocultação dos Engine
membros, a declaração:
myV8->SetState(5, true);
chamaria void SetState( int var, int val )
da classe derivada, convertendo true
para int
.
Se a interface não for virtual e a implementação virtual não for pública, como no seu exemplo, o autor da classe derivada terá menos um problema para pensar e pode simplesmente escrever
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val ) {/*new implementation*/}
};