0
votes

Pourquoi suis-je l'erreur "ne peut accéder au membre privé déclaré en classe" même si j'ai déclaré une classe d'amis

Considérez le code suivant:

template<typename T>
class A
{
    private:
        T value;

    public:
        A(T v){ value = v; }
};

template<typename T>
class B
{
    public:
    T method(A<T> a){ return a.value; }

    friend class A<int>;
};


4 commentaires

Ne devrait-il pas être en classe b


Vous devez autoriser B d'accéder aux données privées d'A.


Classe d'amis A ; Pourquoi limitez-vous à au lieu de ?


@ DAVIDC.RANKIN Je pourrais faire cela, mais je ne pense pas que c'est le problème réel. La raison en est que dans mon code actuel, cela fait partie d'une bibliothèque de mathématiques et je prévois d'avoir des amis pour Int, flotteur, double, complexe. Ceci est juste un exemple simple qui illustre le problème.


3 Réponses :


0
votes
#include <iostream>

template<typename T>
class A
{
    private:
        T value;

    public:
        A(T v){ value = v;}
        T getValue() { return value; }


};

template<typename T>
class B
{
    public:
        friend class A<int>;
        T method(A<T> a){ return a.getValue(); } 

};

int main()
{
    A<int> a(2);
    B<int> b;

    std::cout << b.method(a) << std::endl;
}
Few changes. a.value() value is a private member variable, so we created a getter below getValue() and replaced where needed. 
Also moved friend class A to class B.

3 commentaires

Si je vais utiliser un getter, alors pourquoi devrais-je déclarer une classe d'amis du tout?


@James, je ne pense pas que tu comprends ce qu'est l'ami. Ami ne remplace pas les niveaux d'accès ...


@Omd Compscici Ma compréhension est que votre ami vous permet d'accéder aux membres privés de l'extérieur de la classe aussi longtemps que vous êtes un ami de la classe contenant les membres privés. Avec votre solution, je peux simplement supprimer la ligne "Classe d'amis" et fonctionnera toujours car vous utilisez simplement un getter standard. Encore une fois, je suppose que ma question est, quel est le point de la ligne "Classe d'amis" dans votre solution ...



0
votes
T method(A<T> a){ return a.value; }

  problem here, but why?
Because class B is accessing class A's private member value.

3 commentaires

Pouvez-vous fournir une solution? J'ai essayé de déplacer la classe d'amis A en B, mais cela ne résout pas le problème. J'ai aussi essayé d'avoir déclaré un ami comme ami dans A et B et cela ne fonctionne pas non plus. Peut-être que je manque quelque chose d'évident et une solution explicite pourrait m'aider.


Ne faites pas de privé puisque vous voulez évidemment y accéder à partir d'une autre catégorie s.


Je ne veux pas le rendre public parce que je ne le veux pas dans toutes les classes, mais seulement une petite sélection de classes connexes. C'est pourquoi j'allais utiliser "ami". Je pourrais bien sûr utiliser un getter comme je pense suggéré par Omid Compki



2
votes
template<typename T>
class B;

template<typename T>
class A
{
    private:
        T value;
    public:
        A(T v){ value = v;}
        friend class B<int>;
};

template<typename T>
class B
{
    public:
        T method(A<T> a){ return a.value; }
};
The class A should have class B as a friend , if you want B to use A's private attributes.

3 commentaires

C'est correct, comme c'est la déclaration directe du modèle classe B; avant la définition de modèle classe A {...} . Remarque, l'emplacement de Classe d'amis B ; dans la définition de Classe A n'est pas important et Classe d'amis B ; Est-ce que tout ce qui est nécessaire plutôt que .


Merci! J'aurais pensé que le contraire où la classe B aurait besoin d'avoir une classe A comme ami afin d'accéder aux données privées de classe A. Au lieu de cela, c'était le contraire où la classe A a besoin de classe B comme ami.


Vous auriez également pu utiliser une méthode d'ami: ami tb :: méthode (a ); mais je ne sais pas comment forcer la contrainte au type INT avec cette approche .. .: /