2010-08-25 3 views
1

J'essaie de me lier d'amitié avec une classe pour qu'elle puisse en atteindre un constructeur privé.Se lier d'amitié avec une classe

Dans some_file.h

class B;  

namespace some_name { 
class A { 
    public: 
    A() {} 
    private: 
    A (int x) {} 
    friend class ::B; 
}; 
} 

Dans other_file.h

#include "some_file" 

namespace { 
class B { 
    protected: 
    A* get_a(int x) { return new A(x); } 
}; 
} 

Lors de la compilation de ce code, je reçois - erreur: 'some_name :: A :: A (int)' est privé.

Je maintenant, c'est privé, c'est pourquoi je me suis lié d'amitié avec B. Qu'est-ce que je fais mal ici? Ne pouvez-vous pas vous lier d'amitié avec votre constructeur? Y a-t-il un problème d'espace de noms?

Merci

+1

Pour lier d'amitié avec d'autres classes, simplement don d'un chapeau haut, ont une canne de marche qui vous pratiquiez en virevoltant, et quelques belles chaussures avec l'odeur fraîche du cuir . "Voilà l'homme qui a le scintillement dans les yeux!" les gens vont commenter, ouvrant la porte à de nouvelles opportunités avec de nouvelles classes. –

+1

@Tom: Êtes-vous élevé? – ereOn

Répondre

9

Faire ceci:

namespace { 
class B { 
    protected: 
    A* get_a(int x) { return new A(x) }; 
} 
} 

Vous ne mettez pas B dans la racine namespace (global), mais dans un un anonyme.

Donc, B ne peut pas être atteint par ::B.

Si vous souhaitez que B figure dans l'espace de noms racine (global), ne le placez pas du tout avec namespace. Cela devrait faire l'affaire.

+0

ok, mais si je n'ai aucun contrôle sur l'emplacement de B et qu'il doit s'agir d'un espace de noms anonyme, comment puis-je toujours le faire fonctionner? – izex

+1

@izex: Le rôle de cet espace de noms anonyme est précisément d'interdire les références à ce type en dehors de l'espace de noms anonyme.Sauf si vous déplacez la déclaration 'A' dans le même espace de noms anonyme, il n'y a aucun moyen. – ereOn

+0

Cela est parfaitement logique. Merci. – izex

1

Vous transférez uniquement la classe B référencée et associée dans l'espace de noms global. Pas une classe B dans un espace de noms quoi que ce soit. Vous devez qualifier pleinement le nom de B.

Édition: Merci ereOn.
J'ai fait une légère erreur. Il est vrai que la raison pour laquelle vous avez un problème est que vous avez mal déclaré et mal référé à B, mais ma déclaration initiale n'était pas tout à fait vraie. Vous devez retirer B de l'espace de noms anonyme - il est inutile d'être dans un en-tête de toute façon.

+0

Le nom de 'B' était déjà pleinement qualifié (' :: B') mais je suppose que l'OP signifiait simplement qu'un espace de noms vide résultait de l'espace de noms global. – ereOn

0

Le problème est que vous faites référence à B comme ::B au lieu de B. Cela signifie que vous dites au compilateur que B est un nom global, mais en fait ce n'est pas le cas: il se trouve dans un espace de noms anonyme. Vous n'avez pas besoin de supprimer l'espace de noms anonyme, c'est juste qu'il ne peut pas faire ce que vous attendez de lui. Étant donné que l'espace de noms anonyme est dans un en-tête, cela signifie que l'intérieur de cet espace de noms est lié statiquement à tout fichier d'implémentation qui inclut l'en-tête. Ce n'est pas très utile, parce que vous ne cachez rien. Vous pourriez aussi bien supprimer cet espace de noms anonyme.

0

Can't you befriend your constructor?

Vous pouvez voir ci-dessous

struct B{ 
    B(); 
    void f(); 
}; 

struct A{ 
    friend B::B(); 
private: 
    A(){} 
}; 

B::B(){A a;}  // fine 

void B::f(){A a;} // error 

int main(){ 
} 
Questions connexes