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 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);
精彩评论