Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why method of class does not have access to some field of my class?

I try to implement linked_ptr. It is a study task. It is a part of my code:

template <class T>
class linked_ptr 
{
public:
    //***************
    linked_ptr<T>(linked_ptr<T> const& other)
    {
        p = other.p;

        left_ptr = &other;
        right_ptr = other.right_ptr;

        if (other.right_ptr != nullptr)
        {
            (other.right_ptr)->left_ptr = this;
        }

        other.right_ptr = this;
    }

    template <class U>
    linked_ptr<T>(linked_ptr<U> const& other)
    {
        p = other.p;

        left_ptr = &other;
        right_ptr = other.right_ptr;

        if (other.right_ptr != nullptr)
        {
            (other.right_ptr)->left_ptr = this;
        }

        other.right_ptr = this;
    }

private:
    T *p;
    mutable linked_ptr const* left_ptr;
    mutable linked_ptr const* right_ptr;
};


class A
{
public:
    int a = 0;
    A(int aa)
    {
        a = aa;
    }
};

class B : public A
{
public:
    B(int bb)
    {
        a = bb;
    }
};

int main()
{
    linked_ptr<B> a(new B(5));
    linked_ptr<A> b(a);

    return 0;
}

I have some errors:

cannot access private member declared in class 'smart_ptr::linked_ptr<B>'
cannot access private member declared in class 'smart_ptr::linked_ptr<B>'   
cannot access private member declared in class 'smart_ptr::linked_ptr<B>'
cannot access private member declared in class 'smart_ptr::linked_ptr<B>'
cannot access private member declared in class 'smart_ptr::linked_ptr<B>'
cannot access private member declared in class 'smart_ptr::linked_ptr<B>'
ptr::linked_ptr<B> *' to 'const smart_ptr::linked_ptr<A> *'
ptr::linked_ptr<B> *' to 'const smart_ptr::linked_ptr<A> *'
linked_ptr<A> *const ' to 'const smart_ptr::linked_ptr<B> *'
linked_ptr<A> *const ' to 'const smart_ptr::linked_ptr<B> *'

I don't know what these errors are related. It is interesting, that linked_ptr<T>(linked_ptr<T> const& other) works well, but linked_ptr<T>(linked_ptr<U> const& other) does not.

How can I fix these problems? Can I to combine two copy constructors in one?

P.S. Of course, U is a child of T.

like image 722
Denis Avatar asked Feb 11 '23 16:02

Denis


2 Answers

When T and U are different types, then linked_ptr<T> and linked_ptr<U> are different types. This means they can not see the private members of the other.

You need to make other linked_ptrs friends:

template <class T>
class linked_ptr {
    // The rest...

    template<class U>
    friend class linked_ptr;
};
like image 114
orlp Avatar answered Apr 27 '23 00:04

orlp


You don't have a class, you have a class template. That is, a template, a recipe, for creating classes. In goes a type (for T) and out goes a class. A totally distinct, separate class for each T. Just like classes A and B cannot access each other's private fields, neither can classes linked_ptr<A> and linked_ptr<B> (and linked_ptr<int>, for that matter).

If you need this access, you must add the appropriate friend declaration to your class template:

template <class T>
class linked_ptr 
{
  template <class U>
  friend class linked_ptr;
// ... the rest as before
};
like image 43
Angew is no longer proud of SO Avatar answered Apr 27 '23 00:04

Angew is no longer proud of SO