【问题标题】:Why method of class does not have access to some field of my class?为什么类的方法无法访问我类的某些字段?
【发布时间】:2015-05-16 22:06:47
【问题描述】:

我尝试实现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&lt;T&gt;(linked_ptr&lt;T&gt; const&amp; other) 运行良好,但 linked_ptr&lt;T&gt;(linked_ptr&lt;U&gt; const&amp; other) 却不行。

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

附:当然,UT 的子代。

【问题讨论】:

  • 通常,这样的错误会给出行号;如果您指出这些错误发生在代码中的何处,将会有很大帮助。
  • @Hurkyl,所有错误都发生在linked_ptr&lt;T&gt;(linked_ptr&lt;U&gt; const&amp; other)

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


【解决方案1】:

TU 是不同的类型时,那么linked_ptr&lt;T&gt;linked_ptr&lt;U&gt; 是不同的类型。这意味着他们看不到对方的私人成员。

你需要交其他linked_ptrs 朋友:

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

    template<class U>
    friend class linked_ptr;
};

【讨论】:

    【解决方案2】:

    你没有一个类,你有一个类模板。也就是说,一个模板,一个配方,用于创建类。输入一个类型(T),输出一个类。每个T 都有一个完全不同的独立类。就像 AB 类不能访问彼此的私有字段一样,linked_ptr&lt;A&gt;linked_ptr&lt;B&gt; 类(以及 linked_ptr&lt;int&gt;,就此而言)也不能。

    如果您需要此访问权限,则必须将适当的 friend 声明添加到您的类模板:

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

    【讨论】:

      【解决方案3】:

      其他解决方案仅解决第一个编译错误。使用模板友元声明将允许linked_ptr&lt;A&gt; 访问linked_ptr&lt;B&gt; 私有状态,但它们不允许您将linked_ptr&lt;A&gt; * 分配给linked_ptr&lt;B&gt; *

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

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

      如果你这样做,你不需要朋友声明。 (或者您需要使构造函数更复杂,将link_ptr&lt;U&gt; 变形为linked_ptr&lt;T&gt;。但这需要更智能的指针或克隆或其他东西......这会带来:我不确定这些是什么“智能”指针。如前所述,没有进行内存管理,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;
      

      【讨论】:

      • 如果您想了解更多关于此类智能指针的信息,可以阅读此链接:code.google.com/p/google-breakpad/source/browse/trunk/src/…
      • 在这种情况下,所有权似乎由非模板类型的链接列表linked_ptr_internal 跟踪。因此,没有尝试在模板化复制构造函数中将linked_ptr&lt;U&gt; 分配给linked_ptr&lt;T&gt;。我不确定您要对树做什么,但也许应该检查所有权管理非模板化。
      猜你喜欢
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      • 2015-11-14
      • 2021-05-26
      • 1970-01-01
      • 2019-09-09
      • 1970-01-01
      相关资源
      最近更新 更多