zoukankan      html  css  js  c++  java
  • 从MFC中的CSinpleList学到的东西

    源自:小银

    stack是一种先进后出(First in last out)的数据结构,queue是一种先进先出(first in first out)的数据结构,在stl中实现方法是用了把deque双向队列封装了一下(具体可以查看<<stl源妈解析>>大概是第4章).
    今天剥离MFC中CWinThread的类时,发现是一个MFC存放线程信息的一个队列类CSimpleList,是个队列的类和以前看到的方法都不一样它用了位移来得到p->next(比较牛啊).具体代码从MFC中剥离了出来,根据这种想法又写了stack和queue的两个类,其实是想写list的嫌麻烦,就改简单的了.重在思想.

    先给出 CSimpleList代码

    Simplelist.h
    #ifndef __JONES__CSIMPLELIST__
    #define __JONES__CSIMPLELIST__

    class CSimpleList
    {
    public:
     CSimpleList(
    int nNextOffset = 0);
     
    void Construct(int nNextOffset);

    //操作
     BOOL IsEmpty() const;
     
    void AddHead(void* p);
     
    void RemoveAll();
     
    void* GetHead() const;
     
    void* GetNext(void* p) const;
     BOOL Remove(
    void* p);
     
    void** GetNextPtr(void* p) const

    private:
     
    void* m_pHead;
     size_t m_nNextOffset;  
    //pNext的位移偏量

    }
    ;

    //对CSimpleList的一个封装
    template<class TYPE>
    class CTypedSimpleList : public CSimpleList
    {
    public:
     CTypedSimpleList(
    int nNextOffset = 0)
      : CSimpleList(nNextOffset) 
    { }
     
    void AddHead(TYPE p)
      
    { CSimpleList::AddHead(p); }
     TYPE GetHead()
      
    return (TYPE)CSimpleList::GetHead(); }
     TYPE GetNext(TYPE p)
      
    return (TYPE)CSimpleList::GetNext(p); }
     BOOL Remove(TYPE p)
      
    return CSimpleList::Remove((TYPE)p); }
     
    operator TYPE()
      
    return (TYPE)CSimpleList::GetHead(); }
    }
    ;

    #endif

    #include 
    "stdafx.h"
    #include 
    "SimpleList.h"

    CSimpleList::CSimpleList(
    int nNextOffset)

     m_pHead 
    = NULL; 
     m_nNextOffset 
    = nNextOffset; 
    }


    void CSimpleList::Construct(int nNextOffset) 

     assert(m_pHead 
    == NULL); 
     m_nNextOffset 
    = nNextOffset; 
    }


    BOOL CSimpleList::IsEmpty() 
    const

     
    return m_pHead == NULL; 
    }



    void** CSimpleList::GetNextPtr(void* p) const

     assert(p 
    != NULL); 
     
    return (void**)((BYTE*)p+m_nNextOffset);   
    //重点啊 配合下面的g_list.Construct(offsetof(CThreadData, pNext)); 一起看,然后画个图 是不是得到是pNext的位置
    }



    void CSimpleList::RemoveAll()

     m_pHead 
    = NULL; 
    }



    void* CSimpleList::GetHead() const

     
    return m_pHead; 
    }


    void* CSimpleList::GetNext(void* prevElement) const

     
    return *GetNextPtr(prevElement); 
    }


    void CSimpleList::AddHead(void* p)
    {
     assert(p 
    != NULL);
     assert(
    *GetNextPtr(p) == NULL);

     
    *GetNextPtr(p) = m_pHead;
     m_pHead 
    = p;
    }


    BOOL CSimpleList::Remove(
    void* p)
    {
     assert(p 
    != NULL);

     
    if (m_pHead == NULL)
      
    return FALSE;

     BOOL bResult 
    = FALSE;
     
    if (m_pHead == p)
     
    {
      m_pHead 
    = *GetNextPtr(p);
      bResult 
    = TRUE;
     }

     
    else
     
    {
      
    void* pTest = m_pHead;
      
    while (pTest != NULL && *GetNextPtr(pTest) != p)
       pTest 
    = *GetNextPtr(pTest);
      
    if (pTest != NULL)
      
    {
       
    *GetNextPtr(pTest) = *GetNextPtr(p);
       bResult 
    = TRUE;
      }

     }

     
    return bResult;
    }


    //调用了

    struct CThreadData
    {
     CThreadData
    * pNext; 
     
    int nCount;        
     LPVOID
    * pData;      
    }
    ;


    CTypedSimpleList
    <CThreadData*> g_list;
    int main(int argc, char* argv[])
    {
     g_list.Construct(offsetof(CThreadData, pNext)); 
    //得到pNext的和CThreadData的偏量
     CThreadData* pData=NULL,
     pData 
    = new CThreadData;
     pData
    ->nCount = 0;
     pData
    ->pData = NULL;
     pData
    ->pNext=NULL;
     g_list.AddHead(pData);

     pData 
    = new CThreadData;
     pData
    ->nCount = 1;
     pData
    ->pData = NULL;
     pData
    ->pNext=NULL;
     g_list.AddHead(pData);

     pData 
    = new CThreadData;
     pData
    ->nCount = 2;
     pData
    ->pData = NULL;
     pData
    ->pNext=NULL;
      
     g_list.AddHead(pData);

     pData
    =g_list;
     
    while(pData=g_list.GetNext(pData))
     
    {
          printf(
    "%d\r\n",pData->nCount);
     }

    .delete掉new出来的东西(略) 可以调Remove() 然后delete
    }

     //下面是我自己根据这个原理写的stock和queue 最后用模版封装了一下

    #ifndef __JONES_QUEUE__STOCK
    #define __JONES_QUEUE__STOCK

    class ListBase //list基类
    {
    public:
     
    void Construct(int nNextOffset); //pNext的位移

    protected:
     
    void** GetNextPtr(void* p) const//利用位移得到pNext地址
     size_t m_nNextOffset; //偏移量
    }
    ;


    /********************************************************************/
    /******************QueueList 先进先出********************************/
    /********************************************************************/
    class QueueList : public ListBase
    {
    public:
     QueueList(
    int nNextOffset=0);

    //操作
     bool empty() const;
     
    void* front() const//得到栈的第一个数据
     void pop(); //出栈
     void push(void* p); //压栈
    private:
     
    void* m_pHead; //
     void* m_pTail; //
    }
    ;


    /********************************************************************/
    /******************StockList 先进后出********************************/
    /********************************************************************/
    class StockList : public ListBase
    {
    public:
     StockList(
    int nNextOffset=0);
     
    void pop(); //出栈
     void push(void* p); //压栈
     void* front() const//得到栈的第一个数据
    private:
     
    void* m_pHead; //
    }
    ;

    /********************************************************************/
    /*封装了一下 好看点而已(起码也用到模版了,现在流行的技术,呵呵..) */
    /********************************************************************/
    template 
    <typename TYPE,typename LISTTYPE=QueueList /*list类型*/>
    class SpecialList : public LISTTYPE
    {
    public:
     SpecialList(
    int nNextOffset=0)
      : LISTTYPE(nNextOffset)  
    {}

     TYPE front()
      
    return (TYPE)LISTTYPE::front(); }

     
    void push(TYPE p)
      
    { LISTTYPE::push(p); }

    }
    ;
    #endif

    //调用的例子
    struct CThreadData
    {
     CThreadData
    * pNext; 
     
    int nCount;     
     LPVOID
    * pData; 
    }
    ;

    SpecialList
    <CThreadData*,QueueList> g_Queue;

    int main(int argc, char* argv[])

     g_Queue.Construct(offsetof(CThreadData, pNext));
     CThreadData
    * pData=NULL,*pTemp=NULL;
     pData 
    = new CThreadData;
     pData
    ->nCount = 0;
     pData
    ->pData = NULL;
     pData
    ->pNext=NULL;
     g_Queue.push(pData);

     pData 
    = new CThreadData;
     pData
    ->nCount = 1;
     pData
    ->pData = NULL;
     pData
    ->pNext=NULL;
     g_Queue.push(pData);

     pData 
    = new CThreadData;
     pData
    ->nCount = 2;
     pData
    ->pData = NULL;
     pData
    ->pNext=NULL; 
     g_Queue.push(pData);

     
    while(pData=g_Queue.front())
     
    {
      printf(
    "%d\r\n",pData->nCount);
      g_Queue.pop();
      delete pData;
     }

     
      
    return 0;
    }


    最后忘了说还有1点就是 如果你用的是继承的数据
    class CNoTrackObject
    {
    public:
     
    virtual ~CNoTrackObject() {};

    }
    ;

    struct CThreadData : public CNoTrackObject
    {
     CThreadData
    * pNext; 
     
    int nCount;         
     LPVOID
    * pData;     )
    }
    ;


    那pNext位移的偏量就不是0了是4,具体可以查看<<c++对象模型>>

  • 相关阅读:
    ACM ICPC 2008–2009 NEERC MSC A, B, C, G, L
    POJ 1088 滑雪 DP
    UVA 11584 最短回文串划分 DP
    POJ 2531 Network Saboteur DFS+剪枝
    UVa 10739 String to Palindrome 字符串dp
    UVa 11151 Longest Palindrome 字符串dp
    UVa 10154 Weights and Measures dp 降维
    UVa 10271 Chopsticks dp
    UVa 10617 Again Palindrome 字符串dp
    UVa 10651 Pebble Solitaire 状态压缩 dp
  • 原文地址:https://www.cnblogs.com/powersun/p/972028.html
Copyright © 2011-2022 走看看