开发者

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

开发者 https://www.devze.com 2023-02-01 14:06 出处:网络
I\'ve been thinking of this for hours, but still can\'t understand... This is an open source definition of a linked list.

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 in开发者_如何学编程voke 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!


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.


Can't you just inherit from NPT_List, and then promote Item to public?

class FooList : public NPT_List<Foo>
{
  public:
    class Item;

  ...
} 


The methods that use the Item type are utility methods that shouldn't have been part of the public interface. Use the Iterator versions instead to access the same functionality:

NPT_Result   Add(const T& data);
NPT_Result   Insert(const Iterator where, const T& data);
NPT_Result   Erase(const Iterator position);


The interface to the class is incorrect. Add, Detach, and Insert should take T& parameters, not Item&. Detach will also need an iterator parameter to indicate which element to detach.

Edit: As someone else pointed out there are already Add and Insert methods that take a const T& parameter, so these others were probably all intended to be protected. A minor bug. The thing that's tripping you up is that the Detach method that uses T& is missing. It needs to be added as a new method:

NPT_Result   Detach(const Iterator where, T& data);
0

精彩评论

暂无评论...
验证码 换一张
取 消