Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 朋友类无法访问私有数据_C++_Templates_C++11_G++ - Fatal编程技术网

C++ 朋友类无法访问私有数据

C++ 朋友类无法访问私有数据,c++,templates,c++11,g++,C++,Templates,C++11,G++,这是我的班级宣言: 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 <t

这是我的班级宣言:

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

};
模板
Sptr类{
模板类Sptr;
模板
友元布尔运算符==(常数Sptr&a,常数Sptr&b);
模板
friend Sptr静态指针投射(常量Sptr&sp);
私人:
RC*ref;//引用计数器
T*obj;//指向当前obj的指针
std::函数数据;
布尔ok;
公众:
Sptr();
~Sptr();
模板
Sptr(U*);
Sptr(常数Sptr&);
模板
Sptr(常数Sptr&);
模板
Sptr&运算符=(常量Sptr&);
Sptr&运算符=(常量Sptr&);
无效重置();
T*运算符->()常量
{返回obj;};
T&运算符*()常数
{return*obj;};
T*get()常量
{返回obj;};
显式运算符bool()常量{
返回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静态指针强制转换(常数Sptr&sp){
//做点什么
Sptr回答;
answer.obj=sp.obj;
answer.ref=sp.ref;
answer.destroyData=sp.destroyData;
answer.ok=sp.ok;
返回答案;
}
当我使用以下代码编译时:

    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.
Sptr sp(新衍生);
Sptr sp2(sp);
//Sptr sp3(sp2);//应该给出一个语法错误。
Sptr sp3(静态指针投射(sp2));
//Sptr sp4(动态指针投射(sp2));//应该给出多态性的语法错误。

我已经把它变成了朋友的功能。为什么它不能访问变量以及如何更正它?

这有点棘手。如果替换,代码将编译

template <typename U>
friend Sptr<T> 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;
}
Sptr静态指针转换(常量Sptr&sp){
//做点什么
Sptr回答;
answer.obj=sp.obj;
answer.ref=sp.ref;
answer.destroyData=sp.destroyData;
answer.ok=sp.ok;
返回答案;
}

因此,它尝试访问
Base1
Derived
,但它只是
Derived
的朋友,而不是
Base1
。最后一句话很重要,将其更改为具有两个模板参数的friend函数可以解决此问题。

这有点棘手。如果替换,代码将编译

template <typename U>
friend Sptr<T> 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;
}
Sptr静态指针转换(常量Sptr&sp){
//做点什么
Sptr回答;
answer.obj=sp.obj;
answer.ref=sp.ref;
answer.destroyData=sp.destroyData;
answer.ok=sp.ok;
返回答案;
}

因此,它尝试访问
Base1
Derived
,但它只是
Derived
的朋友,而不是
Base1
。最后一句话很重要,将其更改为具有两个模板参数的friend函数可以解决此问题。

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

template< class u, class v> friend sptr<u> static_pointer_cast(const sptr<v> &sp);
template友元sptr静态指针(const sptr&sp);

您说的是friend
sptr
,这意味着它只能访问sptr的私有成员,并且访问的类型相同。因为sp2不是sptr(t是派生的),所以它不是朋友。尝试:

template< class u, class v> friend sptr<u> static_pointer_cast(const sptr<v> &sp);
template友元sptr静态指针(const sptr&sp);

可能有一种语法来定义原始声明,但这会很棘手。按照您的建议定义两个模板参数可能是最干净、最容易阅读的解决方案。可能有一种语法来定义原始声明,但这将很棘手。按照您的建议定义两个模板参数可能是最干净、最容易阅读的解决方案。两个与您的问题无关的小提示:您不应该在函数实现后加分号。你可以让
操作符==
成为一个成员,因此它不必是你的朋友。这要么是你写问题时的复制粘贴错误,要么是你的代码中的错误:在
静态指针强制转换的实现中,你实际上是在将
Sptr
复制到
Sptr
,然后在中强制转换到
Sptr
返回语句。是否要分配一个
Sptr
,然后复制每个字段?
模板好友类Sptr!=<代码>模板Sptr静态\u指针\u转换(const-Sptr&sp)
两个与问题无关的小提示:不应在函数实现后加分号。你可以让
操作符==
成为一个成员,因此它不必是你的朋友。这要么是你写问题时的复制粘贴错误,要么是你的代码中的错误:在
静态指针强制转换的实现中,你实际上是在将
Sptr
复制到
Sptr
,然后在中强制转换到
Sptr
返回语句。是否要分配一个
Sptr
,然后复制每个字段?
模板好友类Sptr!=<代码>模板Sptr静态\u指针\u转换(常量Sptr&sp)
欢迎来到StackOverflow。注意格式化你的答案。要格式化代码,请在每行前面加4个空格(或按
{}
按钮)。您当前的答案隐藏了模板参数,因为它被解析为HTML…欢迎使用StackOverflow。注意格式化你的答案。要格式化代码,请在每行前面加4个空格(或按
{}
按钮)。您当前的答案隐藏了模板参数,因为它被解析为HTML。。。