2010-07-19 8 views
8

Possible en double:
clean C++ granular friend equivalent? (Answer: Attorney-Client Idiom)En C++, étant donné une fonction membre dans la classe A, pouvons-nous restreindre son accès à seulement la classe B, sans donner à B un accès complet à A?

Je voulais ce une ou deux fois et n'a pas été en mesure de trouver une façon décente de le faire. Dites que j'ai une fonction membre dans la classe A. Je veux être capable d'appeler cette fonction à partir d'une classe B non apparentée, mais ne pas être généralement appelable. Vous pourriez dire, "Bien sûr, rendre la fonction privée et déclarer que B est un ami de A." C'est ce que j'ai fait, mais cela semble un peu exagéré. Je ne veux pas vraiment donner à B l'accès à tout en A, juste la fonction.

En bref: A::func() appelable seulement par la classe B, mais B pas déclaré un ami de A. Possible?

+2

double possible: http://stackoverflow.com/questions/3217390/clean-c-granular-friend-equivalent-answer-attorney-client-idiom –

+0

Ma question est en effet une duplicata de celui-là. Apparemment, ma recherche-foo est faible. –

Répondre

5

Vous pouvez diviser l'interface de A en plusieurs classes de base abstraites pures, puis donner B une référence à l'interface qui a la méthode appropriée. Les autres classes ne recevront que des interfaces qui ne contiennent pas cette méthode. Gardez à l'esprit que ce n'est pas très évolutif, car le nombre d'interfaces peut rapidement devenir très important.

5

Une façon possible pourrait être de créer une classe approuvée qui enveloppe A::func et passe un objet wrapper à B. Cela nécessite à nouveau que wrapper soit un ami de A, mais vous n'avez besoin de gérer qu'une telle classe, alors que toutes les classes externes peuvent utiliser le wrapper.

Exemple:

class Wrapper; 

class A { 
    private: 
    void func(); 
    /* other methods */ 

    public: 
    Wrapper getWrapper(); 

    friend class Wrapper; 
}; 

class Wrapper { 
    private: 
    A &ref; 

    private: 
    Wrapper(A &obj) : ref(obj) { } 

    public: 
    void func() { 
     ref.func(); 
    } 

    friend class A; 
}; 

Wrapper A::getWrapper() { 
    return Wrapper(*this); 
} 
+0

C'est une solution très lourde, surtout si vous avez besoin de le faire à plusieurs endroits. De plus, je ne pense pas que les templates C++ vous donnent un moyen de généraliser cela sur différents noms de fonctions et de classes (bien que je puisse me tromper), ce qui signifie que vous répéterez ceci pour chaque tuple de fonction et de classe que vous voulez activer . –