MFC中CList类使用方法

来源:互联网 发布:淘宝千里眼怎么样 编辑:程序博客网 时间:2024/04/26 20:51

CList是一个双向链表类。

1:Clist类定义在Afxtempl.h 头文件中,因此在使用该类时,需要加这个头文件名。

2、理解CList的声明和构造方法

CList的声明如下:

template< class TYPE, class ARG_TYPE >class CList : public CObject

CList<CPoint, CPoint&> list;

这样就指定了CList中存放的是CPoint类型的引用。

由此,我们知道CList是一个模版类,那么他的两个class是什么意思呢?

下面看一个例子:

CList<CString ,CString&> list;//链表对象1CList<CString,CString> list2;//链表对象2

这里的第一个参数CString是实例化的类型,第二个参数是类的成员函数的参数的调用形式,通常是类型 引用,当然也可以是对象,而不是引用。对象和引用的区别,可以看一下C++基础知识方面的书。
3、使用CList的迭代器
     迭代器是近年在链表使用中的一个常用技术。如果大家学过java,就会知道,在java中,会有专门的一个迭代器类,这个迭代器类用来访问Collect中的数据元素。在mfc中,在CList中,定义了几个迭代器的函数。他们方便了我们去访问数据元素。
GetHeadPositionReturns the position of the head element of the list.GetTailPositionReturns the position of the tail element of the list.GetNextGets the next element for iterating.GetPrevGets the previous element for iterating.
以上是四个迭代器函数。前两个他们的返回值是POSITION,它是mfc中定义的的一种专门访问Collect类的一个数据类型。用他来表示元素的位置。
// abstract iteration positionstruct __POSITION { };typedef __POSITION* POSITION;


以上是在跟踪POSITION定义中找到的。由此,我们知道POSITION是个抽象的迭带器位置。至于怎么实现,我也只能知道这么多,如果有哪位高手知道的话,一定要告诉我们哦。
下面我们利用给出的迭代器函数,对下面建立的链表进行遍历:
CList<CString ,CString&> list;CString str1="hello";CString str2="world";CString str3="my";CString str4="life";list.AddTail(str1);list.AddTail(str2);list.AddTail(str3);list.AddTail(str4);POSITION pos = list.GetHeadPosition();while(pos!=NULL){       pDC->TextOut(200,200,GetNext( POSITION& rPosition ) );//假设代码是在View类中的OnDraw()                                                                                                 //函数里}


这样就完成了对list的遍历。
4、CList的其它函数:
      CList的其它函数,大家可以参考一下MSDN,在那里每个函数都讲得很清楚。这里就不再多介绍。
5、CList的元素
      对于系统定义的类,可以直接在CList中使用。而对于用户自定义的类,如果这个类继承了CObject类,在使用CList时,需要将用户自定义的类实现操作符=的重载,否则系统将会报错。以下举一简单的CNode例子,使之实现操作符=的重载:
class CNode : public CObject{public:      CPoint point;      CNode()     {            point.x=0;            point.y=0;     }     void operator = (CPoint& p)//运算符=的重载    {        point=p;    }};


6、CList的序列化:
     CList是一个继承了CObject的类,并且已经实现了Serialize(CArchive& ar)的函数,所以,对CList进行串行序列化不需要的。
    如果在CList类在CDocument定义了其对象list,那么在文档的Serialize(CArchive& ar)只需作如下修改:
void CDdfDoc::Serialize(CArchive& ar){if (ar.IsStoring()){   // TODO: add storing code here   list.Serialize(ar);}else{   // TODO: add loading code herelist.Serialize(ar);}}


这样,就实现了文档的串行化,如果使用mfc生成的框架,那么我们就可以直接将这个list的数据保存到文件,并能读取了。

CList声明的原型
template<class TYPE, class ARG_TYPE = const TYPE&>class CList : public CObject{protected:struct CNode{CNode* pNext;// 后指针CNode* pPrev;// 前指针TYPE data;// 数据};public:// Construction/* explicit */ CList(INT_PTR nBlockSize = 10);// Attributes (head and tail)// count of elementsINT_PTR GetCount() const;// return m_nCount;INT_PTR GetSize() const;// return m_nCount;BOOL IsEmpty() const;// return m_nCount == 0;// peek at head or tailTYPE& GetHead();// return m_pNodeHead->data;const TYPE& GetHead() const;TYPE& GetTail();// return m_pNodeTail->data;const 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 tailPOSITION AddHead(ARG_TYPE newElement);POSITION AddTail(ARG_TYPE newElement);// add another list of elements before head or after tailvoid AddHead(CList* pNewList);void AddTail(CList* pNewList);// remove all elementsvoid RemoveAll();// iterationPOSITION GetHeadPosition() const;// return (POSITION) m_pNodeHead;POSITION GetTailPosition() const;// return (POSITION) m_pNodeTail;TYPE& GetNext(POSITION& rPosition);// return *Position++const TYPE& GetNext(POSITION& rPosition) const; // return *Position++TYPE& GetPrev(POSITION& rPosition);// return *Position--const TYPE& GetPrev(POSITION& rPosition) const; // return *Position--// getting/modifying an element at a given positionTYPE& GetAt(POSITION position);const TYPE& GetAt(POSITION position) const;void SetAt(POSITION pos, ARG_TYPE newElement);void RemoveAt(POSITION position);// inserting before or after a given positionPOSITION 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 foundPOSITION FindIndex(INT_PTR nIndex) const;// get the 'nIndex'th element (may return NULL)// Implementationprotected:CNode* m_pNodeHead;// 指向链表头的指针CNode* m_pNodeTail;// 指向链表尾的指针INT_PTR m_nCount;// 元素个数CNode* m_pNodeFree;// 空闲节点链表struct CPlex* m_pBlocks;// 数据块载体链表INT_PTR m_nBlockSize;// 每个数据块元素个数CNode* NewNode(CNode*, CNode*);// 创建新节点void FreeNode(CNode*);// 释放节点数据public:~CList();void Serialize(CArchive&);#ifdef _DEBUGvoid Dump(CDumpContext&) const;void AssertValid() const;#endif};

RemoveHead 和 FreeNode 函数
// 删除头部元素,并返回其元素值template<class TYPE, class ARG_TYPE>TYPE CList<TYPE, ARG_TYPE>::RemoveHead(){CNode* pOldNode = m_pNodeHead;TYPE returnValue = pOldNode->data;m_pNodeHead = pOldNode->pNext;if (m_pNodeHead != NULL)m_pNodeHead->pPrev = NULL;elsem_pNodeTail = NULL;FreeNode(pOldNode);return returnValue;}// 释放节点template<class TYPE, class ARG_TYPE>void CList<TYPE, ARG_TYPE>::FreeNode(CNode* pNode){pNode->data.~TYPE();pNode->pNext = m_pNodeFree;// 将节点加入空闲节点链表m_pNodeFree = pNode;m_nCount--;// if no more elements, cleanup completelyif (m_nCount == 0)RemoveAll();}
AddHead(插入元素) 和 NewNode 函数
// 在链表头部插入值为newElement的元素template<class TYPE, class ARG_TYPE>POSITION CList<TYPE, ARG_TYPE>::AddHead(ARG_TYPE newElement){CNode* pNewNode = NewNode(NULL, m_pNodeHead);pNewNode->data = newElement;if (m_pNodeHead != NULL)m_pNodeHead->pPrev = pNewNode;elsem_pNodeTail = pNewNode;m_pNodeHead = pNewNode;return (POSITION) pNewNode;}// 创建一个新节点template<class TYPE, class ARG_TYPE>typename CList<TYPE, ARG_TYPE>::CNode*CList<TYPE, ARG_TYPE>::NewNode(CNode* pPrev, CNode* pNext){if (m_pNodeFree == NULL){// add another blockCPlex* pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CNode));// chain them into free listCNode* pNode = (CNode*) pNewBlock->data();// free in reverse order to make it easier to debugpNode += m_nBlockSize - 1;for (INT_PTR i = m_nBlockSize-1; i >= 0; i--, pNode--){pNode->pNext = m_pNodeFree;m_pNodeFree = pNode;}}CList::CNode* pNode = m_pNodeFree;m_pNodeFree = m_pNodeFree->pNext;pNode->pPrev = pPrev;pNode->pNext = pNext;m_nCount++;::new( (void*)( &pNode->data ) ) TYPE;return pNode;}

AddHead函数(插入链表)
// 在链表头部插入pNewList所指链表  template<class TYPE, class ARG_TYPE>  void CList<TYPE, ARG_TYPE>::AddHead(CList* pNewList)  {      // add a list of same elements to head (maintain order)      POSITION pos = pNewList->GetTailPosition();      while (pos != NULL)          AddHead(pNewList->GetPrev(pos));  } 

RemoveAll函数
// 移除所有的元素  template<class TYPE, class ARG_TYPE>  void CList<TYPE, ARG_TYPE>::RemoveAll()  {      // destroy elements      CNode* pNode;      for (pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)          pNode->data.~TYPE();      m_nCount = 0;      m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;      m_pBlocks->FreeDataChain();          // 释放数据链      m_pBlocks = NULL;  }  


RemoveAt函数
// 移除指定位置的元素  template<class TYPE, class ARG_TYPE>  void CList<TYPE, ARG_TYPE>::RemoveAt(POSITION position)  {      CNode* pOldNode = (CNode*) position;      // remove pOldNode from list      if (pOldNode == m_pNodeHead)          m_pNodeHead = pOldNode->pNext;      else          pOldNode->pPrev->pNext = pOldNode->pNext;      if (pOldNode == m_pNodeTail)          m_pNodeTail = pOldNode->pPrev;      else          pOldNode->pNext->pPrev = pOldNode->pPrev;      FreeNode(pOldNode);     // 释放节点数据。  }  


InsertBefore函数
// 在指定位置之前插入值为newElement的元素。  template<class TYPE, class ARG_TYPE>  POSITION CList<TYPE, ARG_TYPE>::InsertBefore(POSITION position, ARG_TYPE newElement)  {      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)          pOldNode->pPrev->pNext = pNewNode;      else          m_pNodeHead = pNewNode;      pOldNode->pPrev = pNewNode;      return (POSITION) pNewNode;  }  


Find函数
// 从startAfter后开始查找值为searchVaule元素,返回位置  template<class TYPE, class ARG_TYPE>  POSITION CList<TYPE, ARG_TYPE>::Find(ARG_TYPE searchValue, POSITION startAfter) const  {      CNode* pNode = (CNode*) startAfter;      if (pNode == NULL)          pNode = m_pNodeHead;  // start at head      else          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;  }  





RemoveHead 和 FreeNode 函数
0 0