2013-04-18 54 views
0

这里是我的类声明:朋友类不能访问私人数据

template <class T> 
class Sptr { 
    template<typename U> friend class Sptr; 

    template <typename T1, typename T2> 
    friend bool operator==(const Sptr<T1> &a, const Sptr<T2> &b); 

    template <typename U> 
    friend Sptr<T> static_pointer_cast(const Sptr<U> &sp); 

private: 

    RC* ref; //reference counter 
    T* obj;//pointer to current obj 
    std::function<void()> destroyData; 

    bool ok_; 

public: 

    Sptr(); 
    ~Sptr(); 

    template <typename U> 
    Sptr(U *); 

    Sptr(const Sptr &); 

    template <typename U> 
    Sptr(const Sptr<U> &); 

    template <typename U> 
    Sptr<T> &operator=(const Sptr<U> &); 

    Sptr<T> &operator=(const Sptr<T> &); 

    void reset(); 

    T* operator->() const 
    {return obj;}; 

    T& operator*() const 
    {return *obj;}; 

    T* get() const 
    {return obj;}; 

    explicit operator bool() const { 
      return ok_; 
    } 

}; 

下面是代码多数民众赞成在抱怨接入问题

template <typename T, typename U> 
Sptr<T> static_pointer_cast(const Sptr<U> &sp) { 
    //do something 
    Sptr<U> answer; 

    answer.obj = sp.obj; 
    answer.ref = sp.ref; 
    answer.destroyData = sp.destroyData; 
    answer.ok_ = sp.ok_; 

    return answer; 
} 

,当我编译下面的代码:

Sptr<Derived> sp(new Derived); 
    Sptr<Base1> sp2(sp); 

    // Sptr<Derived> sp3(sp2); // Should give a syntax error. 
    Sptr<Derived> sp3(static_pointer_cast<Derived>(sp2)); 
    // Sptr<Derived> sp4(dynamic_pointer_cast<Derived>(sp2)); // Should give syntax error about polymorphism. 

我已经使它成为朋友功能。为什么无法访问变量以及如何纠正?

+2

两个小问题与你的问题没有任何关系:你不应该在函数实现后加分号。你可以使'operator =='成为一个成员,因此它不必是朋友。 – leemes

+0

它要么是当你写你的问题或在您的代码中的错误复制粘贴错误:在'执行static_pointer_cast'你实际上是复制一个'特征码'到'特征码'然后将其转换为'特征码'在return语句中。你想分配一个'Sptr '然后复制每个字段吗? – leemes

+0

'template friend class Sptr;'!='template Sptr static_pointer_cast(const Sptr &sp)' – kfsone

回答

2

这有点棘手。如果你有

template <typename T1, typename T2> 
friend Sptr<T1> static_pointer_cast(const Sptr<T2> &sp); 

原因是以下取代

template <typename U> 
friend Sptr<T> static_pointer_cast(const Sptr<U> &sp); 

你的代码编译(我不是100%肯定,所以请人批准/ DIS-批准):

Sptr<T>被实例化,例如与T = Derived,得到的类定义(Sptr<Derived>)定义具有下列签名朋友功能:

template <typename U> 
friend Sptr<Derived> static_pointer_cast(const Sptr<U> &sp); 

因此,这是其中仅具有一个模板参数的函数。但是你定义的函数有两个模板参数。

呼叫这个模板函数是一个特例,它看起来像这样:

Sptr<Derived> static_pointer_cast(const Sptr<Base1> &sp) { 
    //do something 
    Sptr<Derived> answer; 

    answer.obj = sp.obj; 
    answer.ref = sp.ref; 
    answer.destroyData = sp.destroyData; 
    answer.ok_ = sp.ok_; 

    return answer; 
} 

所以它试图访问Base1Derived,但它只是一个Derived一个朋友,而不是Base1。这最后一句话是重要的,并将其改为两个模板参数解决了这个问题。

+0

可能有一个语法来定义原始声明,但它会很棘手。按照您的建议定义2个模板参数可能是最清晰和最简单的解决方案。 –

1

你说的朋友sptr<t>,这意味着它只能访问sptrs的私有成员为同一类型。因为sp2不是sptr(t是派生的),它不是朋友。尝试:

template< class u, class v> friend sptr<u> static_pointer_cast(const sptr<v> &sp); 
+0

欢迎来到StackOverflow。照顾格式化你的答案。要格式化代码,请在每行之前放置4个空格(或按下“{}”按钮)。您当前的答案隐藏了模板参数,因为它被解析为HTML ... – leemes

相关问题