Question

Je suis en train de comprendre ce qui se passe quand une classe dérivée déclare une fonction virtuelle comme privée. Ce qui suit est le programme que j'ai écrit

#include <iostream>
using namespace std;
class A
{
    public:
        virtual void func() {
        cout<<"A::func called"<<endl;
    }
    private:
};
class B:public A
{
    public:
    B()
    {
        cout<<"B constructor called"<<endl;
    }
    private:
    void func() {
        cout<<"B::func called"<<endl;
    }
};
int main()
{
    A *a = new B();
    a->func();
    return 0;
}

De façon surprenante (pour moi) la sortie est:

B constructor called
B::func called

est-ce pas violer l'accès privé défini pour cette fonction. Est-ce le comportement attendu? Est-ce une solution de contournement est standard ou échappatoire? Les niveaux d'accès contournés lorsque la fonction résolution appelle à travers le VTABLE?

Toute idée de ce comportement serait très utile.

En outre, il a été mentionné que la suppression d'un membre virtuel privé empêcherait d'autres classes d'hériter. Même cela a des problèmes. Modification du programme ci-dessus pour inclure:

class C: public B
{
    public:
    void func() {
        cout<<"C::func called"<<endl;
    }
};

et le programme de test principal:

int main()
{
    A *a = new C();
    a->func();
    return 0;
}

sortie est la suivante:

C::func called
Était-ce utile?

La solution

Le comportement est correct. Chaque fois que vous déclarez votre fonction en tant que « virtuelle », vous demandez au compilateur de générer un appel virtuel, au lieu de l'appel direct à cette fonction. Chaque fois que vous substituez la fonction virtuelle dans la classe descendante, vous spécifiez le comportement de cette fonction (vous ne modifiez pas le mode d'accès pour les clients, qui comptent sur l'interface du « parent de »).

Modification du mode d'accès à la fonction virtuelle dans la classe descendante signifie que vous voulez cacher à ces clients, qui utilisent la classe descendant directement (qui comptent sur l'interface du « enfant »).

Prenons l'exemple:

void process(const A* object) {
   object->func();
}

fonction « processus » repose sur l'interface du parent. Il est prévu de travailler pour toute catégorie, public dérivé de A. Vous ne pouvez pas public-Derive B de A (dire « chaque B est A »), mais cacher une partie de son interface. Ceux qui attendent « A » doit recevoir un « A » entièrement fonctionnel.

Autres conseils

Ce comportement est bien défini. Si un était a ce ne serait pas B* compiler. La raison est que l'accès des membres est résolu statiquement par le compilateur, pas dynamiquement lors de l'exécution. De nombreux livres C ++ suggèrent que vous évitez de codage comme celui-ci parce qu'il confond moins expérimentés codeurs.

Eh bien, vous appelez qui est A::func() bien dans un public objectera il est B remplacée par B::func(). Ceci est un modèle commun avec les conséquences suivantes:

  • func n'est pas destiné à être appelé dérivés objets <=>

  • <=> ne peut pas être redéfinie dans les classes dérivées de <=>

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top