2015-03-14 1 views
4

Я стараюсь реализовать 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<T>(linked_ptr<T> const& other) хорошо работает, но linked_ptr<T>(linked_ptr<U> const& other) нет.

Как исправить эти проблемы? Могу ли я объединить два конструктора копий в один?

P.S. Конечно, U - ребенок T.

+0

Обычно такие ошибки выдают номер строки; это очень поможет, если вы укажете * где * эти ошибки происходят в вашем коде. – Hurkyl

+0

@Hurkyl, все ошибки встречаются в 'linked_ptr (linked_ptr const & other)'. – Denis

ответ

5

Когда T и U - это разные типы, то linked_ptr<T> и linked_ptr<U> - это разные типы. Это означает, что они не могут видеть частных членов другого.

Вы должны сделать другие linked_ptr Друзья пользователя:

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

    template<class U> 
    friend class linked_ptr; 
}; 
2

У вас нет класса, то есть шаблон класса. То есть шаблон, рецепт, для создания классов. В идет тип (для T) и выходит из класса. Совершенно отдельный, отдельный класс для каждого T. Точно так же, как классы A и B не могут получить доступ к частным полям друг друга, ни классы linked_ptr<A> и linked_ptr<B>linked_ptr<int>, если на то пошло).

Если вам нужен этот доступ, необходимо добавить соответствующую friend декларацию шаблона класса:

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

Другие решения только адрес первой ошибки компиляции. Использование объявления шаблона друга позволит linked_ptr<A> получить доступ к приватному состоянию linked_ptr<B>, но они не позволят вам назначить linked_ptr<A> *linked_ptr<B> *.

Дерево само по себе должно быть составлено равномерно базового типа.

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

    return 0; 
} 

Если вы делаете это таким образом, вам не нужна декларация друга. (Или вам нужно сделать конструктор более сложным, превратив link_ptr<U> в linked_ptr<T>. Но для этого нужны умные указатели или клоны или что-то в этом роде: я не уверен, что такое «умный» об этих указателях. , никакого управления памятью не делается и new B(5) теряется)

Кроме того, я знаю, что это просто псевдокод, но B::B(int bb) конструктор должен явно инициализировать базу:.

class B : public A 
{ 
public: 
    B(int bb) 
    : A(bb) 
    { 
    } 
}; 

Один практики я вижу в ваш код, который может добавить к путанице его объявление left_ptr и right_ptr как linked_ptr. C++ позволяет ссылаться на класс по его имени шаблона внутри определения, но это не значит, что это хорошая идея.Я думаю, что код (и вышеприведенная ошибка) более ясны, если код написан как:

T *p; 
mutable linked_ptr<T> const* left_ptr; 
mutable linked_ptr<T> const* right_ptr; 
+1

спасибо за подробный ответ. – Denis

+1

, если вы хотите узнать больше об этом типе умного указателя, вы можете прочитать эту ссылку: https://code.google.com/p/google-breakpad/source/browse/trunk/src/processor/linked_ptr.h – Denis

+0

В этом случае право собственности, как представляется, отслеживается связанным списком не templated типов, 'linked_ptr_internal'. В результате нет попытки присвоить 'linked_ptr ' 'связанному_ptr ' в конструкторе шаблонных копий. Я не уверен, что вы пытаетесь сделать с деревом, но, возможно, нужно провести проверку владения без шаблонов. – sfjac

Смежные вопросы