web-dev-qa-db-fra.com

C++ substitue la méthode virtuelle pure privée en public

Pourquoi cela arrive-t-il?

http://coliru.stacked-crooked.com/a/e1376beff0c157a1

class Base{
private:
    virtual void do_run() = 0;
public:
    void run(){
        do_run();
    }
};

class A : public Base {
public:
    // uplift ??
    virtual void do_run() override {}
};


int main()
{
    A a;
    a.do_run();
}

Pourquoi puis-je remplacer une méthode virtuelle PRIVATE par public?

14
tower120

Selon https://en.cppreference.com/w/cpp/language/virtual#In_detail écrasant la fonction membre virtual d'une base, vous vous préoccupez uniquement du nom de la fonction, des paramètres, de const/volatile-ness et du qualificatif ref. Peu importe le type de retour, le modificateur d'accès ou d'autres éléments qui vous importent. 

La référence liée indique également que:

Base :: vf n'a pas besoin d'être visible (peut être déclaré privé ou hérité à l'aide d'héritage privé) pour être remplacé.

Rien de ce que je peux trouver ne donne explicitement l'autorisation de le faire, mais les règles de neutralisation ne l'empêchent pas. Cela est autorisé en vertu des fonctions virtual et des fonctions qui prévalent sur l'existant et qui ne refusent pas ce cas.

Si vous demandez pourquoi c'est ainsi que le langage est utilisé, vous devrez peut-être demander au comité de normalisation.

15

Ce comportement est destiné. Si une méthode est virtuelle, elle doit être personnalisable à l'aide de classes dérivées, quel que soit le modificateur d'accès.

Voir ici

11
rawberry

Notez que cette implémentation ne change pas la façon dont la classe de base est accédée et une construction:

Base& b = a;
b.do_run();

ne fonctionnera pas. 

Je me souviens que certains motifs ont été décrits plus en détail dans "Effective C++" de Scott Meyers. Mais la fonctionnalité clé est de pouvoir utiliser cette flexibilité dans le sens opposé, de remplacer les membres de la classe de base publique par des fonctions privées dans une classe dérivée, forçant le client à utiliser la classe de base comme interface et à ne pas être tenté d'utiliser dérivé qui devrait rester une implémentation cachée.

2
jszpilewski

Pourquoi je peux remplacer la méthode virtuelle PRIVATE par public ???

Parce que vous considérez que la méthode de base est privée sous un mauvais angle. B::do_run étant privé signifie "seuls les membres et amis de cette classe peuvent l'utiliser". Pour interdire aux classes dérivées de la remplacer, nous aurions besoin d'un spécificateur distinct, mais nous pouvons simplement le rendre non virtual. La classe A d'un autre côté permet à quiconque d'appeler A::do_run() et il appartient au concepteur de la classe A de le décider. Donc, il n'y a pas de soulèvement comme vous le voyez.

2
Slava

Si l'intention est d'écrire un code privé pour la classe de base et d'empêcher toute possibilité de la remplacer, implémentez la fonction privée dans la classe de base et déclarez-la final, sinon: quand quelqu'un devrait-il utiliser des virtuals? ISOCPP.ORG FAQ

0
Amit G.