Search code examples
c++classprotected

How to call a method passing an object of a class defined as protected


I've been thinking of this for hours, but still can't understand... This is an open source definition of a linked list.

template <typename T> 
class NPT_List 
{
protected:
    class Item;

public:
    // types
    typedef T Element;

    class Iterator {
    public:
        Iterator() : m_Item(NULL) {}
        explicit Iterator(Item* item) : m_Item(item) {}
        Iterator(const Iterator& copy) : m_Item(copy.m_Item) {}
        T&  operator*()  const { return m_Item->m_Data; }
        T*  operator->() const { return &m_Item->m_Data;}
        Iterator& operator++()  { // prefix
            m_Item = m_Item->m_Next;
            return (*this); 
        }
        Iterator operator++(int) { // postfix
            Iterator saved_this = *this;
            m_Item = m_Item->m_Next;
            return saved_this;
        }
        Iterator& operator--() { // prefix
            m_Item = m_Item->m_Prev;
            return (*this); 
        }
        Iterator operator--(int) { // postfix
            Iterator saved_this = *this;
            m_Item = m_Item->m_Prev;
            return saved_this;
        }
        operator bool() const {
            return m_Item != NULL;
        }
        bool operator==(const Iterator& other) const {
            return m_Item == other.m_Item;
        }
        bool operator!=(const Iterator& other) const {
            return m_Item != other.m_Item;
        }
        void operator=(const Iterator& other) {
            m_Item = other.m_Item;
        }
        void operator=(Item* item) {
            m_Item = item;
        }

    private:
        Item* m_Item;

        // friends
        friend class NPT_List<T>;
    };

    // methods
                 NPT_List<T>();
                 NPT_List<T>(const NPT_List<T>& list);
                ~NPT_List<T>();
    NPT_Result   Add(const T& data);
    NPT_Result   Insert(const Iterator where, const T& data);
    NPT_Result   Remove(const T& data, bool all=false);
    NPT_Result   Erase(const Iterator position);
    NPT_Result   PopHead(T& data);
    bool         Contains(const T& data) const;
    NPT_Result   Clear();
    NPT_Result   Get(NPT_Ordinal index, T& data) const;
    NPT_Result   Get(NPT_Ordinal index, T*& data) const;
    NPT_Cardinal GetItemCount() const { return m_ItemCount; }
    Iterator     GetFirstItem() const { return Iterator(m_Head); }
    Iterator     GetLastItem() const  { return Iterator(m_Tail); }
    Iterator     GetItem(NPT_Ordinal index) const;

    // list manipulation
    NPT_Result   Add(NPT_List<T>& list);
    NPT_Result   Remove(const NPT_List<T>& list, bool all=false);

    // item manipulation
    NPT_Result   Add(Item& item);
    NPT_Result   Detach(Item& item);
    NPT_Result   Insert(const Iterator where, Item& item);

    // list operations
    // keep these template members defined here because MSV6 does not let
    // us define them later
    template <typename X> 
    NPT_Result Apply(const X& function) const
    {                          
        Item* item = m_Head;
        while (item) {
            function(item->m_Data);
            item = item->m_Next;
        }

        return NPT_SUCCESS;
    }

    template <typename X, typename P> 
    NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
    {                          
        Item* item = m_Head;
        while (item) {
            NPT_Result return_value;
            if (predicate(function(item->m_Data), return_value)) {
                if (match) *match = true;
                return return_value;
            }
            item = item->m_Next;
        }

        if (match) *match = false;
        return NPT_SUCCESS;
    }

    template <typename P> 
    Iterator Find(const P& predicate, NPT_Ordinal n=0) const
    {
        Item* item = m_Head;
        while (item) {
            if (predicate(item->m_Data)) {
                if (n == 0) {
                    return Iterator(item);
                }
                --n;
            }
            item = item->m_Next;
        }

        return Iterator(NULL);
    }

    // operators
    void operator=(const NPT_List<T>& other);
    bool operator==(const NPT_List<T>& other) const;
    bool operator!=(const NPT_List<T>& other) const;

protected:
    // types
    class Item 
    {
    public:
        // methods
        Item(const T& data) : m_Next(0), m_Prev(0), m_Data(data) {}

        // members
        Item* m_Next;
        Item* m_Prev;
        T     m_Data;

        // friends
        //friend class NPT_List<T>;
        //friend class NPT_List<T>::Iterator;
    };

    // members
    NPT_Cardinal m_ItemCount;
    Item*        m_Head;
    Item*        m_Tail;
};

I need to invoke the method Detach to avoid an element of this list to be deallocated when the list goes out of scope (I see that the destructor deletes all the elements). My question is: how do I invoke it? I can't create an instance of Item, as the class Item is protected. So, how is this list supposed to work? If necessary I can of course modify the list, but I'm really interested in how it is supposed to work as I'm trying to learn C++ and so I would like to understand.

Many thanks for any help!


Solution

  • This class is nonsense. You note yourself that you don't see how you'd call Detach(), and indeed I don't see how you'd call Detach() either. Also, on the one hand you have protected members in NPT_List but on the other hand the class has a non-virtual destructor. These are mixed messages. As with a girl with such traits (or a guy; check what's appropriate for you), you should really stay away from it.