2010-01-27 11 views
2

Disons que j'ai deux classes Foo et Bar, et je veux faire des amis Foo avec Bar sans changer Foo. Voici ma tentative:Modèle friend mixin?

class Foo 
{ 
    public: 
     Foo(){} 

    private: 
     void privateFunction(){} 
}; 

template <class friendly, class newFriend> 
class friends : public friendly 
{ 
    private: 
     friend newFriend; 
}; 

class Bar 
{ 
    public: 
     Bar(){} 

     void callFriendlyFunction() 
     { 
      friendlyFoo.privateFunction(); 
     } 

    private: 
     friends<Foo, Bar> friendlyFoo; 
}; 

int main(int argc, char* argv[]) 
{ 
    Bar bar; 

    bar.callFriendlyFunction(); 

    return 0; 
} 

Obtenir une erreur du compilateur d'essayer d'appeler une fonction privée, donc apparemment il ne fonctionnait pas. Des idées?

+1

+1: "foo amical" - Je creuse le son de:> –

+2

l'amitié n'est pas héritée –

+0

Je n'essaie pas de faire ça. – drby

Répondre

2

Cela ne fonctionne pas, parce que friends n'a pas accès à privateFunction de toute façon, parce que c'est private (les classes descendantes n'ont pas accès aux champs privés de toute façon). Si vous voulez déclarer privateFunction comme protected, cela fonctionnera.

Voici un nice paper sur les Mixins en C++. (Lien PDF)

+0

Duh. J'ai compris qu'il me manquait quelque chose d'évident. Merci de l'avoir signalé. – drby

+0

@drby: notez cependant que la réponse de David est toujours là - ce n'est pas permis dans le standard (je crois que c'est son mot), donc ça ne peut pas être portable entre les compilateurs. –

1

Seule une classe peut déclarer qui sont ses amis. Ils ne peuvent pas être injectés de l'extérieur. Cela prend tout son sens: si le langage l'autorisait, il pourrait tout simplement oublier le mot-clé private, après tout, tout code destiné à accéder aux membres privés pourrait simplement utiliser cette astuce. Notez que l'ajout de la relation d'ami dans un objet dérivé n'aidera pas, car la méthode n'est pas accessible depuis le modèle dérivé. Toute autre approche que vous pouvez essayer est hackery et non-portable (réécrire le même en-tête en changeant le private pour public semblera fonctionner dans de nombreuses situations, mais il échouera dans certains cas de coin). Notez également que dans un modèle de classe, vous ne pouvez pas déclarer un argument de type comme ami, il est explicitement interdit dans le standard actuel, même si cette limitation sera supprimée dans la prochaine norme.

0

Vous devriez probablement faire

void privateFunction(){} 

protégé.

Oups, j'ai oublié que vous ne pouvez pas modifier Foo. Pas d'autre moyen de le faire, afaik.