from:
1 http://hi.baidu.com/jiaxi2000/blog/item/d3d02b3f3b1f6aee54e72381.html
CList的用法
2007-06-21 09:26
|
这是一个集合类,也是一个双向链表类,是一个类模板
他的定义如下:
template< class
TYPE
, class
ARG_TYPE
>class CList : public CObject
使用
第一个参数是实例化的类型,第二个参数是类的成员函数的参数的调用形式,通常是类型 引用
一个矩形类Rectangle的类模板:
template
<
class
T
>
class
Rectangle
{
private: T width, height; public: Rectangle(T w, T h); //构造函数 T area(); }
;
在类中,形参T被引用在数据成员width和height的类型及成员函数area返回值的类型上,它是根据将来
程序中声明时指定的类型而定,如在主程序中声明:
Rectangle<int> r1(20,3);
则类模板中的形参T会以int替代,产生以整数为主的Rectangle对象r1 ;
另外,成员函数如果
设计在类外,除了要标明其所属的类名称外,还需要加上模板的声明,且类名称也要加上用
尖括号括起来的形参行。如上例中的成员函数Rectangle(T w, T h)和area(),其写法如下:
template
<
class
T
>
Rectangle
<
T
>
::Rectangle(T w,T h)![]()
...
{ width = w; height = h; }
![]() template
<
class
T
>
T Rectangle
<
T
>
::area()![]()
...
{ return width*height; }
--------------
具有固定类型的类模板
类模板的形参行,不仅可以使用未定类型的类,也可指定固定的类型,如下:
template
<
class
T,
int
n
>
class
Array
...
{ private: T data[n]; public:![]() Array()...{} //构造函数 void add_data(int i, T d); //将数据填入数组中 Array<T,n > operator+(Array<T,n> a); //数组相加 void display(); }
;
如使用这类模板时,如下:
Array<double, 3> dbl1;
表示声明了一个Array对象,其中的数据是double类型,且其数组大小为3,其作用相当于声明了
double data[3].
=================
Afxtempl.h 中的CList
//
CList<TYPE, ARG_TYPE>
template
<
class
TYPE,
class
ARG_TYPE
>
class
CList :
public
CObject![]()
...
{ protected: struct CNode![]() ...{ CNode* pNext; CNode* pPrev; TYPE data; }; public: // Construction CList(int nBlockSize = 10);![]() // Attributes (head and tail) // count of elements int GetCount() const; BOOL IsEmpty() const;![]() // peek at head or tail TYPE& GetHead(); TYPE GetHead() const; TYPE& GetTail(); TYPE GetTail() const;![]() // Operations // get head or tail (and remove it) - don't call on empty list ! TYPE RemoveHead(); TYPE RemoveTail();![]() // add before head or after tail POSITION AddHead(ARG_TYPE newElement); POSITION AddTail(ARG_TYPE newElement);![]() // add another list of elements before head or after tail void AddHead(CList* pNewList); void AddTail(CList* pNewList);![]() // remove all elements void RemoveAll();![]() // iteration POSITION GetHeadPosition() const; POSITION GetTailPosition() const; TYPE& GetNext(POSITION& rPosition); // return *Position++ TYPE GetNext(POSITION& rPosition) const; // return *Position++ TYPE& GetPrev(POSITION& rPosition); // return *Position-- TYPE GetPrev(POSITION& rPosition) const; // return *Position--![]() // getting/modifying an element at a given position TYPE& GetAt(POSITION position); TYPE GetAt(POSITION position) const; void SetAt(POSITION pos, ARG_TYPE newElement); void RemoveAt(POSITION position);![]() // inserting before or after a given position POSITION InsertBefore(POSITION position, ARG_TYPE newElement); POSITION InsertAfter(POSITION position, ARG_TYPE newElement);![]() // helper functions (note: O(n) speed) POSITION Find(ARG_TYPE searchValue, POSITION startAfter = NULL) const; // defaults to starting at the HEAD, return NULL if not found POSITION FindIndex(int nIndex) const; // get the 'nIndex'th element (may return NULL)![]() // Implementation protected: CNode* m_pNodeHead; CNode* m_pNodeTail; int m_nCount; CNode* m_pNodeFree; struct CPlex* m_pBlocks; int m_nBlockSize;![]() CNode* NewNode(CNode*, CNode*); void FreeNode(CNode*);![]() public: ~CList(); void Serialize(CArchive&); #ifdef _DEBUG void Dump(CDumpContext&) const; void AssertValid() const; #endif }
;![]() ![]()
/**/
/////////////////////////////////////////////////////////////////////////////
//
CList<TYPE, ARG_TYPE> inline functions
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE
int
CList
<
TYPE, ARG_TYPE
>
::GetCount()
const
![]()
...
{ return m_nCount; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE BOOL CList
<
TYPE, ARG_TYPE
>
::IsEmpty()
const
![]()
...
{ return m_nCount == 0; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE
&
CList
<
TYPE, ARG_TYPE
>
::GetHead()![]()
...
{ ASSERT(m_pNodeHead != NULL); return m_pNodeHead->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE CList
<
TYPE, ARG_TYPE
>
::GetHead()
const
![]()
...
{ ASSERT(m_pNodeHead != NULL); return m_pNodeHead->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE
&
CList
<
TYPE, ARG_TYPE
>
::GetTail()![]()
...
{ ASSERT(m_pNodeTail != NULL); return m_pNodeTail->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE CList
<
TYPE, ARG_TYPE
>
::GetTail()
const
![]()
...
{ ASSERT(m_pNodeTail != NULL); return m_pNodeTail->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE POSITION CList
<
TYPE, ARG_TYPE
>
::GetHeadPosition()
const
![]()
...
{ return (POSITION) m_pNodeHead; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE POSITION CList
<
TYPE, ARG_TYPE
>
::GetTailPosition()
const
![]()
...
{ return (POSITION) m_pNodeTail; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE
&
CList
<
TYPE, ARG_TYPE
>
::GetNext(POSITION
&
rPosition)
//
return *Position++
![]()
...
{ CNode* pNode = (CNode*) rPosition; ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); rPosition = (POSITION) pNode->pNext; return pNode->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE CList
<
TYPE, ARG_TYPE
>
::GetNext(POSITION
&
rPosition)
const
//
return *Position++
![]()
...
{ CNode* pNode = (CNode*) rPosition; ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); rPosition = (POSITION) pNode->pNext; return pNode->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE
&
CList
<
TYPE, ARG_TYPE
>
::GetPrev(POSITION
&
rPosition)
//
return *Position--
![]()
...
{ CNode* pNode = (CNode*) rPosition; ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); rPosition = (POSITION) pNode->pPrev; return pNode->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE CList
<
TYPE, ARG_TYPE
>
::GetPrev(POSITION
&
rPosition)
const
//
return *Position--
![]()
...
{ CNode* pNode = (CNode*) rPosition; ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); rPosition = (POSITION) pNode->pPrev; return pNode->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE
&
CList
<
TYPE, ARG_TYPE
>
::GetAt(POSITION position)![]()
...
{ CNode* pNode = (CNode*) position; ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); return pNode->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE TYPE CList
<
TYPE, ARG_TYPE
>
::GetAt(POSITION position)
const
![]()
...
{ CNode* pNode = (CNode*) position; ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); return pNode->data; }
template
<
class
TYPE,
class
ARG_TYPE
>
AFX_INLINE
void
CList
<
TYPE, ARG_TYPE
>
::SetAt(POSITION pos, ARG_TYPE newElement)![]()
...
{ CNode* pNode = (CNode*) pos; ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); pNode->data = newElement; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
CList
<
TYPE, ARG_TYPE
>
::CList(
int
nBlockSize)![]()
...
{ ASSERT(nBlockSize > 0);![]() m_nCount = 0; m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL; m_pBlocks = NULL; m_nBlockSize = nBlockSize; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::RemoveAll()![]()
...
{ ASSERT_VALID(this);![]() // destroy elements CNode* pNode; for (pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext) DestructElements<TYPE>(&pNode->data, 1);![]() m_nCount = 0; m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL; m_pBlocks->FreeDataChain(); m_pBlocks = NULL; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
CList
<
TYPE, ARG_TYPE
>
::
~
CList()![]()
...
{ RemoveAll(); ASSERT(m_nCount == 0); }
![]() ![]()
/**/
/////////////////////////////////////////////////////////////////////////////
//
Node helpers
//
//
Implementation note: CNode's are stored in CPlex blocks and
//
chained together. Free blocks are maintained in a singly linked list
//
using the 'pNext' member of CNode with 'm_pNodeFree' as the head.
//
Used blocks are maintained in a doubly linked list using both 'pNext'
//
and 'pPrev' as links and 'm_pNodeHead' and 'm_pNodeTail'
//
as the head/tail.
//
//
We never free a CPlex block unless the List is destroyed or RemoveAll()
//
is used - so the total number of CPlex blocks may grow large depending
//
on the maximum past size of the list.
//
template
<
class
TYPE,
class
ARG_TYPE
>
CList
<
TYPE, ARG_TYPE
>
::CNode
*
CList
<
TYPE, ARG_TYPE
>
::NewNode(CList::CNode
*
pPrev, CList::CNode
*
pNext)![]()
...
{ if (m_pNodeFree == NULL)![]() ...{ // add another block CPlex* pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CNode));![]() // chain them into free list CNode* pNode = (CNode*) pNewBlock->data(); // free in reverse order to make it easier to debug pNode += m_nBlockSize - 1; for (int i = m_nBlockSize-1; i >= 0; i--, pNode--)![]() ...{ pNode->pNext = m_pNodeFree; m_pNodeFree = pNode; } } ASSERT(m_pNodeFree != NULL); // we must have something![]() CList::CNode* pNode = m_pNodeFree; m_pNodeFree = m_pNodeFree->pNext; pNode->pPrev = pPrev; pNode->pNext = pNext; m_nCount++; ASSERT(m_nCount > 0); // make sure we don't overflow![]() ConstructElements<TYPE>(&pNode->data, 1); return pNode; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::FreeNode(CList::CNode
*
pNode)![]()
...
{ DestructElements<TYPE>(&pNode->data, 1); pNode->pNext = m_pNodeFree; m_pNodeFree = pNode; m_nCount--; ASSERT(m_nCount >= 0); // make sure we don't underflow![]() // if no more elements, cleanup completely if (m_nCount == 0) RemoveAll(); }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
POSITION CList
<
TYPE, ARG_TYPE
>
::AddHead(ARG_TYPE newElement)![]()
...
{ ASSERT_VALID(this);![]() CNode* pNewNode = NewNode(NULL, m_pNodeHead); pNewNode->data = newElement; if (m_pNodeHead != NULL) m_pNodeHead->pPrev = pNewNode; else m_pNodeTail = pNewNode; m_pNodeHead = pNewNode; return (POSITION) pNewNode; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
POSITION CList
<
TYPE, ARG_TYPE
>
::AddTail(ARG_TYPE newElement)![]()
...
{ ASSERT_VALID(this);![]() CNode* pNewNode = NewNode(m_pNodeTail, NULL); pNewNode->data = newElement; if (m_pNodeTail != NULL) m_pNodeTail->pNext = pNewNode; else m_pNodeHead = pNewNode; m_pNodeTail = pNewNode; return (POSITION) pNewNode; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::AddHead(CList
*
pNewList)![]()
...
{ ASSERT_VALID(this);![]() ASSERT(pNewList != NULL); ASSERT_VALID(pNewList);![]() // add a list of same elements to head (maintain order) POSITION pos = pNewList->GetTailPosition(); while (pos != NULL) AddHead(pNewList->GetPrev(pos)); }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::AddTail(CList
*
pNewList)![]()
...
{ ASSERT_VALID(this); ASSERT(pNewList != NULL); ASSERT_VALID(pNewList);![]() // add a list of same elements POSITION pos = pNewList->GetHeadPosition(); while (pos != NULL) AddTail(pNewList->GetNext(pos)); }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
TYPE CList
<
TYPE, ARG_TYPE
>
::RemoveHead()![]()
...
{ ASSERT_VALID(this); ASSERT(m_pNodeHead != NULL); // don't call on empty list !!! ASSERT(AfxIsValidAddress(m_pNodeHead, sizeof(CNode)));![]() CNode* pOldNode = m_pNodeHead; TYPE returnValue = pOldNode->data;![]() m_pNodeHead = pOldNode->pNext; if (m_pNodeHead != NULL) m_pNodeHead->pPrev = NULL; else m_pNodeTail = NULL; FreeNode(pOldNode); return returnValue; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
TYPE CList
<
TYPE, ARG_TYPE
>
::RemoveTail()![]()
...
{ ASSERT_VALID(this); ASSERT(m_pNodeTail != NULL); // don't call on empty list !!! ASSERT(AfxIsValidAddress(m_pNodeTail, sizeof(CNode)));![]() CNode* pOldNode = m_pNodeTail; TYPE returnValue = pOldNode->data;![]() m_pNodeTail = pOldNode->pPrev; if (m_pNodeTail != NULL) m_pNodeTail->pNext = NULL; else m_pNodeHead = NULL; FreeNode(pOldNode); return returnValue; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
POSITION CList
<
TYPE, ARG_TYPE
>
::InsertBefore(POSITION position, ARG_TYPE newElement)![]()
...
{ ASSERT_VALID(this);![]() if (position == NULL) return AddHead(newElement); // insert before nothing -> head of the list![]() // Insert it before position CNode* pOldNode = (CNode*) position; CNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode); pNewNode->data = newElement;![]() if (pOldNode->pPrev != NULL)![]() ...{ ASSERT(AfxIsValidAddress(pOldNode->pPrev, sizeof(CNode))); pOldNode->pPrev->pNext = pNewNode; } else![]() ...{ ASSERT(pOldNode == m_pNodeHead); m_pNodeHead = pNewNode; } pOldNode->pPrev = pNewNode; return (POSITION) pNewNode; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
POSITION CList
<
TYPE, ARG_TYPE
>
::InsertAfter(POSITION position, ARG_TYPE newElement)![]()
...
{ ASSERT_VALID(this);![]() if (position == NULL) return AddTail(newElement); // insert after nothing -> tail of the list![]() // Insert it before position CNode* pOldNode = (CNode*) position; ASSERT(AfxIsValidAddress(pOldNode, sizeof(CNode))); CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext); pNewNode->data = newElement;![]() if (pOldNode->pNext != NULL)![]() ...{ ASSERT(AfxIsValidAddress(pOldNode->pNext, sizeof(CNode))); pOldNode->pNext->pPrev = pNewNode; } else![]() ...{ ASSERT(pOldNode == m_pNodeTail); m_pNodeTail = pNewNode; } pOldNode->pNext = pNewNode; return (POSITION) pNewNode; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::RemoveAt(POSITION position)![]()
...
{ ASSERT_VALID(this);![]() CNode* pOldNode = (CNode*) position; ASSERT(AfxIsValidAddress(pOldNode, sizeof(CNode)));![]() // remove pOldNode from list if (pOldNode == m_pNodeHead)![]() ...{ m_pNodeHead = pOldNode->pNext; } else![]() ...{ ASSERT(AfxIsValidAddress(pOldNode->pPrev, sizeof(CNode))); pOldNode->pPrev->pNext = pOldNode->pNext; } if (pOldNode == m_pNodeTail)![]() ...{ m_pNodeTail = pOldNode->pPrev; } else![]() ...{ ASSERT(AfxIsValidAddress(pOldNode->pNext, sizeof(CNode))); pOldNode->pNext->pPrev = pOldNode->pPrev; } FreeNode(pOldNode); }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
POSITION CList
<
TYPE, ARG_TYPE
>
::FindIndex(
int
nIndex)
const
![]()
...
{ ASSERT_VALID(this);![]() if (nIndex >= m_nCount || nIndex < 0) return NULL; // went too far![]() CNode* pNode = m_pNodeHead; while (nIndex--)![]() ...{ ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); pNode = pNode->pNext; } return (POSITION) pNode; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
POSITION CList
<
TYPE, ARG_TYPE
>
::Find(ARG_TYPE searchValue, POSITION startAfter)
const
![]()
...
{ ASSERT_VALID(this);![]() CNode* pNode = (CNode*) startAfter; if (pNode == NULL)![]() ...{ pNode = m_pNodeHead; // start at head } else![]() ...{ ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); pNode = pNode->pNext; // start after the one specified }![]() for (; pNode != NULL; pNode = pNode->pNext) if (CompareElements<TYPE>(&pNode->data, &searchValue)) return (POSITION)pNode; return NULL; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::Serialize(CArchive
&
ar)![]()
...
{ ASSERT_VALID(this);![]() CObject::Serialize(ar);![]() if (ar.IsStoring())![]() ...{ ar.WriteCount(m_nCount); for (CNode* pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)![]() ...{ ASSERT(AfxIsValidAddress(pNode, sizeof(CNode))); SerializeElements<TYPE>(ar, &pNode->data, 1); } } else![]() ...{ DWORD nNewCount = ar.ReadCount(); while (nNewCount--)![]() ...{ TYPE newData; SerializeElements<TYPE>(ar, &newData, 1); AddTail(newData); } } }
![]() #ifdef _DEBUG template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::Dump(CDumpContext
&
dc)
const
![]()
...
{ CObject::Dump(dc);![]() dc << "with " << m_nCount << " elements"; if (dc.GetDepth() > 0)![]() ...{ POSITION pos = GetHeadPosition(); while (pos != NULL)![]() ...{ dc << " "; DumpElements<TYPE>(dc, &((CList*)this)->GetNext(pos), 1); } }![]() dc << " "; }
![]() template
<
class
TYPE,
class
ARG_TYPE
>
void
CList
<
TYPE, ARG_TYPE
>
::AssertValid()
const
![]()
...
{ CObject::AssertValid();![]() if (m_nCount == 0)![]() ...{ // empty list ASSERT(m_pNodeHead == NULL); ASSERT(m_pNodeTail == NULL); } else![]() ...{ // non-empty list ASSERT(AfxIsValidAddress(m_pNodeHead, sizeof(CNode))); ASSERT(AfxIsValidAddress(m_pNodeTail, sizeof(CNode))); } }
#endif
//
_DEBUG
=========================
因此如下:
typedef CList<CString ,CString &> strlist;
strlist str;
or
CList<CString ,CString &> str;
这样就定义了一个CString类型的双向链表str;
这样可以看出
ARG_TYPE主要指定
CList的方法对于TYPE的引用方法。
例如: 1) CList<string, string> list; POSITION AddHead(string newElement); 这是AddHead参数为 传值 2) CList<string, string&> list; POSITION AddHead(string& newElement); 这是AddHead参数为传 引用 |
}

Array()
}

9203

被折叠的 条评论
为什么被折叠?



