0

Consider the following code:

#include <iostream>

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

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

        friend class A<int>;
};

template<typename T>
class B
{
    public:
        T method(A<T> a){ return a.value; }  // problem here, but why?
};

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

    std::cout << b.method(a) << std::endl;
}

Why do I still get the error: "'A::value': cannot access private member declared in class 'A'" even though I have declared A as a friend class for the template type int?

Edit Note that moving the friend class line inside B also does not work:

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>;
};
James
  • 398
  • 1
  • 6
  • 19

3 Answers3

2
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.

  • That's correct as is the forward-declaration of `templateclass B;` prior to the definition of `templateclass A {...}`. Note, the location of `friend class B;` in the definition of `class A` isn't important and `friend class B;` is all that is needed rather than ``. – David C. Rankin Feb 01 '20 at 23:47
  • Thanks! I would have thought the opposite where class B would need to have class A as a friend in order to access class A's private data. Instead it was the opposite where class A needs class B as a friend. – James Feb 01 '20 at 23:51
  • you could have also used a friend method : `friend T B::method(A);` but I do not know how to force the constraint to the int type with this approach ... :/ – Etienne Salimbeni Feb 02 '20 at 00:07
0
#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.

Omid CompSCI
  • 1,861
  • 3
  • 17
  • 29
  • If I am going to use a getter, then why would I need to declare a friend class at all? – James Feb 01 '20 at 23:27
  • @James, I don't think you understand what friend is for. Friend does not override access levels... – Omid CompSCI Feb 02 '20 at 05:51
  • @Omd CompSCI My understanding is that friend allows you to access private members from outside the class as long as you are a friend of the class containing the private members. With your solution I can just delete the "friend class" line and it will still work since you are just using a standard getter. So again I guess my question to you is, what is the point of the "friend class" line in your solution... – James Feb 02 '20 at 23:37
0
T method(A<T> a){ return a.value; }

problem here, but why?

Because class B is accessing class A's private member value.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • Can you provide a solution. I tried moving the friend class A into B but this does not fix the problem. I also tried having the A declared as a friend in both A and B and that also does not work. Perhaps I am missing something obvious and a explicit solution could help me. – James Feb 01 '20 at 23:41
  • Don't make `value` `private` since you obviously want to access it from other `class`s. – Paul Evans Feb 02 '20 at 00:31
  • I don't want to make it public because I don't want it accessible from ALL classes though, only a small selection of related classes. Thats why I was going to use "friend". I could of course use a getter as I think suggested by Omid CompSCI – James Feb 02 '20 at 23:41