Pourquoi le C++ ami de classe ont besoin d'une déclaration anticipée que dans d'autres espaces de noms?
Supposons que j'ai une classe F
que doit être un ami pour les classes G
(dans l'espace de noms global) et C
(dans l'espace de noms A
).
- pour être ami de
A::C
,F
doit être déclaré avant. - pour être ami de
G
, peu avant la déclaration deF
est nécessaire. - de même, une classe
A::BF
peut être ami deA::C
sans déclaration anticipée
Le code suivant illustre et compile avec GCC 4.5, VC++ 10 et au moins avec un autre compilateur.
class G {
friend class F;
int g;
};
//without this forward declaration, F can't be friend to A::C
class F;
namespace A {
class C {
friend class ::F;
friend class BF;
int c;
};
class BF {
public:
BF() { c.c = 2; }
private:
C c;
};
} //namespace A
class F {
public:
F() { g.g = 3; c.c = 2; }
private:
G g;
A::C c;
};
int main()
{
F f;
}
Ce me semble incohérent. Est-il une raison à cela ou est-ce juste une décision de conception de la norme?
Vous devez vous connecter pour publier un commentaire.
C++
StandardISO/IEC 14882:2003(E)
7.3.1.2 de l'espace de Noms des définitions de membre
Paragraphe 3
Votre
friend class BF;
est une déclaration deA::BF
dans Un espace de noms plutôt que de l'espace de noms global. Vous avez besoin de la mondial de déclaration préalable pour éviter cette nouvelle déclaration.friend class ::F;
" (comme indiqué dans l'OP du code), donc explicitement poussantF
dans l'espace de noms global. Je pense que la réponse est dans la ligne de "qualifiée-id ne déclare jamais un nouveau nom", mais je suis pas sûr exactement ce que dit la norme sur ce point.Prenons en compte ces 3 lignes de code à partir de votre échantillon:
C++ standard dans le paragraphe 7.3.1.2, point 3 ( espace de Noms des définitions de membre) dit:
Et la ligne 2 suit exactement ce que la norme exige.
Toute confusion est parce que "l'ami de la déclaration" est faible, vous devez fournir une déclaration anticipée pour une autre utilisation.
Parce qu'il ne serait pas logique d'être en mesure de déclarer quelque chose dans l'espace de noms global si vous êtes à l'intérieur d'un
namespace {}
bloc. La raisonfriend class BF;
œuvres, c'est qu'il agit comme un implicite de la déclaration anticipée.