不能访问同一类的私有成员



我正在实现一个智能指针类作为练习。考虑以下内容:

class Base1 {
    protected:
        Base1() : derived_destructor_called(false) {
            printf("Base1::Base1()n");
        }
    private:
        Base1(const Base1 &); // Disallow.
        Base1 &operator=(const Base1 &); // Disallow.
    protected:
        ~Base1() {
            printf("Base1::~Base1()n");
            assert(derived_destructor_called);
        }
    protected:
        bool derived_destructor_called;
};
class Derived : public Base1 {
        friend void basic_tests_1();
    private:
        Derived() {printf("Derived::Derived()n");}
        Derived(const Derived &); // Disallow.
        Derived &operator=(const Derived &); // Disallow.
    public:
        ~Derived() {
            printf("Derived::~Derived()n");
            derived_destructor_called = true;
        }
        int value;
};

和下面的测试代码:

            Sptr<Derived> sp(new Derived);
            // // Test template copy constructor.
            Sptr<Base1> sp3(sp);

产生以下错误:

Sptr.cpp: In instantiation of ‘my::Sptr<T>::Sptr(const my::Sptr<U>&) [with U = Derived; T = Base1]’:
Sptr.cpp:272:35:   required from here
Sptr.cpp:41:6: error: ‘Derived* my::Sptr<Derived>::obj’ is private
Sptr.cpp:117:86: error: within this context
Sptr.cpp:42:13: error: ‘my::RC* my::Sptr<Derived>::ref’ is private
Sptr.cpp:117:86: error: within this context
Sptr.cpp:43:31: error: ‘std::function<void()> my::Sptr<Derived>::destroyData’ is private
Sptr.cpp:117:86: error: within this context

这怎么可能?我指的是同一个类中的同一个类变量。

下面是模板类原型及其构造函数声明:

template <class T>
class Sptr {
private:
    //some kind of pointer
        //one to current obj
    T* obj;
    RC* ref;
    std::function<void()> destroyData;
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;};
    //operator unspecified_bool_type() const;
    //overload *,->,=,copy-constructor
    // const-ness should be preserved.
    // Test for null using safe-bool idiom
    // Static casting, returns a smart pointer
};

编辑

我在模板类中声明了一个模板友元,如下所示:
template<typename U> friend class Sptr;

解决了上面的错误。但是它产生了新的错误!

测试代码:

        Sptr<Base1> sp2;
        {
            Sptr<Derived> sp(new Derived);
            // // Test template copy constructor.
            Sptr<Base1> sp3(sp);
            sp2 = sp;
            sp2 = sp2;
        }
错误:

Sptr.cpp: In instantiation of ‘my::Sptr<T>& my::Sptr<T>::operator=(const my::Sptr<U>&) [with U = Derived; T = Base1]’:
Sptr.cpp:274:23:   required from here
Sptr.cpp:128:9: error: comparison between distinct pointer types ‘my::Sptr<Base1>*’ and ‘const my::Sptr<Derived>*’ lacks a cast
Sptr.cpp:212:9: error: ‘Base1::~Base1()’ is protected
Sptr.cpp:132:21: error: within this context
Sptr.cpp: In instantiation of ‘my::Sptr<T>& my::Sptr<T>::operator=(const my::Sptr<T>&) [with T = Base1]’:
Sptr.cpp:275:23:   required from here
Sptr.cpp:212:9: error: ‘Base1::~Base1()’ is protected
Sptr.cpp:154:21: error: within this context

当我已经使它成为模板友时,这怎么可能呢?在重载

=操作符下面
template <typename T> 
Sptr<T>& Sptr<T>::operator=(const Sptr<T> &t) {
    std::cout<<"= const <T>n";
    if(this != &t) {
        if(ref->Release() == 0) {
            if(obj)
                delete obj;
            delete ref;       
        }
        obj = t.obj;
        ref = t.ref;
        destroyData = t.destroyData;
        ref->AddRef();
    }
    return *this;
}
template <typename T> 
template <typename U> 
Sptr<T>& Sptr<T>::operator=(const Sptr<U> &t) {
    std::cout<<"= const <U>n";
    if(this != &t) {
        if(ref->Release() == 0) {
            if(obj)
                delete obj;
            delete ref;       
        }
        obj = t.obj;
        ref = t.ref;
        destroyData = t.destroyData;
        ref->AddRef();
    }
    return *this;
}

类不同;构造函数是

my::Sptr<Base1>::Sptr(const my::Sptr<Derived>&)

,你试图访问my::Sptr<Derived>的成员。

需要声明一个模板友元:

template<typename U> friend class Sptr;

我指的是同一个类中的同一个类变量。

不,你不是。也许你指的是同一类模板的相同成员,我猜是

之类的
    template <typename U> 
    Sptr(const Sptr<U> & other) : obj(other.obj), ref(other.ref) {}

但是你不是访问同一个的成员,因为Sptr<Base>Sptr<Derived>是模板的不同实例化,因此是不同的类,不能接触彼此的私有。

更新到您的编辑:您现在得到的错误与访问权限无关,但它再次与Sptr<Base>Sptr<Derived>是不同的类有关,因此指向它们的指针是不同的指针类型,无法比较。
您所显示的代码是相同模板实例化(Sptr<T>)的operator=,但错误发生在不同模板实例化(Sptr<U>)的操作符中。我猜你也有地址比较,这是不必要的,因为Sptr<T>不能和Sptr<U>有相同的地址。

关于受保护的~Base的第二个错误很明显:你把~Base设置为受保护的非虚拟的,这意味着你不会通过删除Base*指针来破坏Base对象。这同样适用于Base的智能指针,因为它们会使用您禁止的多态删除。解决方案:将~Base设为公有虚拟

它们不是同一个类。它看起来像是在抱怨你试图从Sptr<Base1>访问Sptr<Derived>的成员——看看错误消息开头的类型变量实例化。

模板,当它们的类型变量被填充时,生成的是看起来非常相似的全新类,所以MyClass<string>MyClass<vector<int>>是不一样的。

相关内容

  • 没有找到相关文章

最新更新