为什么类的方法无法访问我班级的某些字段?

时间:2015-03-14 12:30:24

标签: c++ templates c++11 smart-pointers type-inference

我尝试实施linked_ptr。这是一项研究任务。这是我的代码的一部分:

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;
}

我有一些错误:

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> *'

我不知道这些错误有什么关系。有趣的是,linked_ptr<T>(linked_ptr<T> const& other)效果很好,但linked_ptr<T>(linked_ptr<U> const& other)没有。

我该如何解决这些问题?我可以将两个复制构造函数合并在一个吗?

P.S。当然,UT的孩子。

3 个答案:

答案 0 :(得分:5)

TU的类型不同时,linked_ptr<T>linked_ptr<U>是不同的类型。这意味着他们无法看到对方的私人成员。

你需要建立其他linked_ptr朋友:

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

    template<class U>
    friend class linked_ptr;
};

答案 1 :(得分:2)

你没有一个类,你有一个类模板。也就是说,一个用于创建类的模板,一个配方。在一个类型(对于T)和一个类中。每个T都有一个完全不同的独立类。就像类AB无法访问彼此的私有字段一样,类linked_ptr<A>linked_ptr<B>(以及linked_ptr<int>也无法访问。

如果您需要此访问权限,则必须在类模板中添加相应的friend声明:

template <class T>
class linked_ptr 
{
  template <class U>
  friend class linked_ptr;
// ... the rest as before
};

答案 2 :(得分:1)

其他解决方案仅解决第一个编译错误。使用模板朋友声明将允许linked_ptr<A>访问linked_ptr<B>私人状态,但他们不允许您将linked_ptr<A> *分配给linked_ptr<B> *

树本身应该由基本类型统一组成。

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

    return 0;
}

如果你这样做,你不需要朋友声明。 (或者你需要使构造函数更复杂,将link_ptr<U>变形为linked_ptr<T>。但是这需要更聪明的指针或克隆或某些东西......这会引起:我不知道是什么关于这些指针是非常聪明的。如上所述,没有进行内存管理,new B(5)丢失了。)

另外,我知道这只是伪代码,但B::B(int bb)构造函数需要显式初始化它的基础:

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

我在您的代码中看到的一种做法可能会使left_ptrright_ptr的声明混淆为linked_ptr。 C ++允许您通过定义中的模板名称来引用类,但这并不意味着它是一个好主意。如果代码写成:

,我认为代码(和上面的错误)更清楚
T *p;
mutable linked_ptr<T> const* left_ptr;
mutable linked_ptr<T> const* right_ptr;