友元类无法访问私有数据

Friend class not able to access private data

本文关键字:数据 访问 友元      更新时间:2023-10-16

下面是我的类声明:

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.

我已经把它设为好友功能。为什么它不能访问变量以及如何纠正它?

这有点棘手。如果替换

,代码就会编译
template <typename U>
friend Sptr<T> static_pointer_cast(const Sptr<U> &sp);

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

原因如下(我不是百分之百确定,所以请有人赞成/不赞成):

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

所以它试图访问 Base1 Derived,但它只是Derived的朋友,不是Base1的朋友。最后这句话很重要,把它改成带有两个模板参数的友元函数就解决了这个问题。

您说的是好友sptr<t>,这意味着它只能访问相同类型的sptrs的私有成员。因为sp2不是sptr(t是派生出来的),所以它不是友元。试一试:

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