La question est dans le sujet suggèrent une jolie commune de la confusion. La confusion est assez commun, que C++ FAQ préconisé contre l'utilisation privée virtuals, pour une longue période, en raison de la confusion qui semblait être une mauvaise chose.
Donc, pour se débarrasser de la confusion d'abord: Oui, privés des fonctions virtuelles peut être redéfinie dans les classes dérivées. Les méthodes des classes dérivées ne peux pas les appeler des fonctions virtuelles de la classe de base, mais ils peuvent fournir leur propre mise en œuvre. Selon Herb Sutter, ayant publique non-interface virtuelle dans la classe de base et d'une salle de mise en œuvre qui peut être personnalisé dans les classes dérivées, permet une meilleure séparation de la spécification de l'interface à partir de la spécification de la mise en œuvre de personnalisation du comportement". Vous pouvez en lire plus à ce sujet dans son article "Virtualité".
Il y a cependant une chose plus intéressante dans le code que vous avez présenté, qui mérite un peu plus d'attention, à mon avis. L'interface publique se compose d'un ensemble de surcharge de non-fonctions virtuelles et les fonctions d'appels non-public, non surchargé des fonctions virtuelles. Comme d'habitude dans le C++ monde, c'est un idiome, il a un nom, et bien sûr, il est utile. Le nom est (surprise, surprise!)
"Public Surchargé Non-Virtuals Appel Protégé Non Surchargé Virtuals"
Il aide à gérer correctement la règle de masquage. Vous pouvez en lire plus à ce sujet ici, mais je vais essayer de l'expliquer en peu de temps.
Imaginez, que les fonctions virtuelles de la Engine
classe sont également de son interface et c'est un ensemble de fonctions surchargées qui n'est pas virtuelle pure. Si ils étaient virtuelle pure, on pouvait encore rencontrer le même problème, comme décrit ci-dessous, mais plus bas dans la hiérarchie de classe.
class Engine
{
public:
virtual void SetState( int var, bool val ) {/*some implementation*/}
virtual void SetState( int var, int val ) {/*some implementation*/}
};
Maintenant, supposons que vous voulez créer une classe dérivée, et vous devez fournir un nouveau seulement la mise en œuvre de la méthode, qui prend deux entiers en tant qu'arguments.
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 vous avez oublié de mettre l'aide de la déclaration dans la classe dérivée (ou de redéfinir la seconde surcharge), vous pourriez avoir de la difficulté dans le scénario ci-dessous.
MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);
Si vous n'avez pas d'empêcher la dissimulation de l' Engine
des membres, la déclaration:
myV8->SetState(5, true);
appellerait void SetState( int var, int val )
de la classe dérivée, convertir true
de int
.
Si l'interface n'est pas du virtuel et du virtuel, de la mise en œuvre est non-public, comme dans votre exemple, l'auteur de la classe dérivée a un problème de moins à penser et peut simplement écrire
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val ) {/*new implementation*/}
};