web-dev-qa-db-fra.com

Les classes internes en C ++ sont-elles automatiquement amies?

Si je définis une classe interne en C++, est-ce automatiquement un ami de la classe qui la contient? Par exemple, est-ce légal:

class Outer {
public:
    class Inner {
    public:
        void mutateOuter(Outer& o);
    };

private:
    int value;
};

void Outer::Inner::mutateOuter(Outer& o) {
    o.value ++; // Legal?  Or not?
}

Je demande parce que sur certains compilateurs que j'ai essayés (VS2003) ce code ne fonctionnera pas, mais j'ai entendu au moins anecdotiquement qu'il fonctionne sur certains compilateurs. Je ne trouve pas de section pertinente dans la spécification C++ à ce sujet, et si quelqu'un peut citer quelque chose de spécifique qui dirait que c'est légal ou non, ce serait formidable.

69
templatetypedef

Après avoir posé plus ou moins la même question ici moi-même, je voulais partager la réponse (apparemment) mise à jour pour C++ 11:

Cité de https://stackoverflow.com/a/14759027/1984137 :

standard 11,7,1 $

"Une classe imbriquée est membre et en tant que telle a les mêmes droits d'accès que tout autre membre. Les membres d'une classe englobante n'ont pas d'accès spécial aux membres d'une classe imbriquée; les règles d'accès habituelles doivent être respectées"

et les règles d'accès habituelles précisent que:

"Un membre d'une classe peut également accéder à tous les noms auxquels la classe a accès ..."

des exemples spécifiques ont été donnés dans la norme:

class E {
    int x;
    class B { };

    class I {
        B b; // OK: E::I can access E::B
        int y;
        void f(E* p, int i) {
            p->x = i; // OK: E::I can access E::x
        }
    };
}
65
hcc23

Jusqu'à C++ 11 (c'est-à-dire C++ 98 et C++ 03)

En C++ 98 et C++ 03, la classe imbriquée ne peut pas accéder aux membres private et protected de la classe englobante par défaut.

Le standard C++ (2003) dit en $ 11.8/1 [class.access.nest],

Les membres d'une classe imbriquée n'ont pas d'accès spécial aux membres d'une classe englobante, ni aux classes ou fonctions qui ont accordé l'amitié à une classe englobante; les règles d'accès habituelles (article 11) doivent être respectées. Les membres d'une classe englobante n'ont pas d'accès spécial aux membres d'une classe imbriquée; les règles d'accès habituelles (article 11) doivent être respectées.

Exemple de la norme elle-même:

class E 
{
    int x;
    class B { };
    class I 
    {
        B b; // error: E::B is private
        int y;
        void f(E* p, int i)
        {
           p->x = i; // error: E::x is private
        }
   };
   int g(I* p)
   {
       return p->y; // error: I::y is private
   }
};

Depuis C++ 11

La restriction ci-dessus a été supprimée depuis C++ 11. Maintenant, les classes imbriquées can accèdent aux membres private et protected de la classe englobante:

class E 
{
    int x;
    class B { };
    class I 
    {
        B b; // ok: even though E::B is private
        int y;
        void f(E* p, int i)
        {
           p->x = i; // ok: even though E::x is private
        }
   };
   int g(I* p)
   {
       return p->y; // ok: even though I::y is private
   }
};

J'espère que cela pourra aider.

37
Nawaz

Étant donné que le questionneur semble avoir accepté l'une des réponses, il ne s'agit que d'une supplémentation.
La norme semble avoir modifié les spécifications concernant l'accessibilité.

Le § 11.8/1 en C++ 98 stipule:

Les membres d'une classe imbriquée n'ont aucun accès spécial aux membres d'une classe englobante, ni aux classes ou fonctions qui ont accordé l'amitié à une classe englobante; les règles d'accès habituelles doivent être respectées.

Le § 11.8/1 dans N1804 (après TR1) stipule:

Une classe imbriquée est membre et, en tant que telle, a les mêmes droits d'accès que tout autre membre.

Je pense que les compilateurs C++ actuels obéissent à des spécifications plus récentes.

16
Ise Wisteria

Cette réponse se rapporte à la spécification (obsolète) C++ 03. La réponse acceptée à cette question est plus à jour.

Eh bien, je me sens stupide de poser cette question maintenant parce que je viens de trouver la partie pertinente de la spécification qui couvre cela: §11.8/1:

Les membres d'une classe imbriquée n'ont aucun accès spécial aux membres d'une classe englobante, ni aux classes ou fonctions qui ont accordé l'amitié à une classe englobante; les règles d'accès habituelles (article 11) doivent être respectées. Les membres d'une classe englobante n'ont pas d'accès spécial aux membres d'une classe imbriquée; les règles d'accès habituelles (article 11) doivent être respectées

(Mon accent)

Il semble donc que non, les classes internes n'ont pas de privilèges d'accès spéciaux.

4
templatetypedef

Je ne connais pas l'emplacement précis du haut de ma tête, mais je me souviens avoir lu les spécifications et découvert que toutes les données privées d'une classe sont cachées de toutes les autres classes, y compris les classes imbriquées.

Fondamentalement, l'imbrication d'une classe définit une certaine portée, pas des privilèges d'accès.

3
Ken Wayne VanderLinde