简体   繁体   中英

Why can't my friend class access a private member?

I thought when a class declared a friend class, that friends could access the declarer's private members? This doesn't seem to be the case, or I've done something wrong. I'm trying to access "first" or "last" in OULinkedList. When I try to use "first" or "last" I get a "not declared in this scope" error.

I need access to "first" because without it my next function will never return the first value of the linked list and I'm not sure how else to do it.

For example if I just want to print out the objects in my list, the following while loop always skips the first object.

while(enumerator.hasNext()){
    cout << enumerator.next();
}

Which is obviously not what I want.

#include "OULink.h"
#include "Comparator.h"
#include "OULinkedListEnumerator.h"

// OULinkedList stands for Ordered, Unique Linked List. It is a linked list that is always maintained in
// order (based on the comparator provided to it when the list is created) and that only contains unique
// items (that is, duplicates are not allowed)
template <typename T>
class OULinkedList {
    template <typename F>
    friend class OULinkedListEnumerator;
private:
    Comparator<T>* comparator = NULL;               // used to determine list order and item equality
    unsigned long size = 0;                         // actual number of items currently in list
    OULink<T>* first = NULL;                        // pointer to first link in list
    OULink<T>* last = NULL;


template <typename T>
class OULinkedListEnumerator : public Enumerator<T>
{
private:
    OULink<T>* current;
    int firstNode = 0;
public:
    OULinkedListEnumerator(OULink<T>* first);
    bool hasNext() const;
    T next();
    T peek() const;
};

// Implementation goes here
template<typename T>
OULinkedListEnumerator<T>::OULinkedListEnumerator(OULink<T>* first){
    this->current = first;
}
template<typename T>
bool OULinkedListEnumerator<T>::hasNext() const{

    if(this->current->next != NULL){
        return true;
    }else{
        return false;
    }

}
template<typename T>
T OULinkedListEnumerator<T>::next(){
    
    
    T successorNode = *this->current->next->data;
    this->current = this->current->next;
    return successorNode;
}
template<typename T>
T OULinkedListEnumerator<T>::peek() const{
    if(current != NULL){
        return *current->data;
    }else{
        throw new ExceptionLinkedListAccess;
    }
}
  1. The description you posted suggest that your code compiled successfully. In that case what private access problems are you talking about in your question's title? Access control in C++ is a purely compile-time concept. If your code compiled sucessfully, then it has no problems with private access.

  2. Your class template OULinkedListEnumerator is a nested class template in OULinkedList class template. Just like any nested class, it is supposed to have full access to private members of the enclosing class template OULinkedList without any need for any friend declarations.

  3. Just in case, when you make a friend declaration for a yet-unknown entity, the entity is assumed to be a member of the enclosing namespace scope. So your

    template <typename F> friend class OULinkedListEnumerator;

    refers to a global class template ::OULinkedListEnumerator and makes it a friend. Later you declare a nested class template OULinkedList::OULinkedListEnumerator . This is a completely different class template. It is not a friend. (But it doesn't need to be, see 2).

  4. You are not allowed to reuse template parameter names in nested template declarations. You have to change the name of the nested template parameter from T to something else. In fact, I'm surprised you managed to compile the code to the point of some alleged "access problem" without hitting this parameter naming issue first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM