文档模板管理者类CDocManager
在"文档/视图"架构的MFC程序中,提供了文档模板管理者类CDocManager,由它管理应用程序所包含的文档模板。我们先看看这个类的声明:
///////////////////////////////////////////////////////////////////////////// // CDocTemplate manager object class CDocManager : public CObject { DECLARE_DYNAMIC(CDocManager) public:
// Constructor CDocManager();
//Document functions virtual void AddDocTemplate(CDocTemplate* pTemplate); virtual POSITION GetFirstDocTemplatePosition() const; virtual CDocTemplate* GetNextDocTemplate(POSITION& pos) const; virtual void ReGISterShellFileTypes(BOOL bCompat); void UnregisterShellFileTypes(); virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName); // open named file virtual BOOL SaveAllModified(); // save before exit virtual void CloseAllDocuments(BOOL bEndSession); // close documents before exiting virtual int GetOpenDocumentCount();
// helper for standard commdlg dialogs virtual BOOL DoPromptFileName(CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate);
//Commands // Advanced: process async DDE request virtual BOOL OnDDECommand(LPTSTR lpszCommand); virtual void OnFileNew(); virtual void OnFileOpen();
// Implementation protected: CPtrList m_templateList; int GetDocumentCount(); // helper to count number of total documents
public: static CPtrList* pStaticList; // for static CDocTemplate objects static BOOL bStaticInit; // TRUE during static initialization static CDocManager* pStaticDocManager; // for static CDocTemplate objects
public: virtual ~CDocManager(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif }; |
从上述代码可以看出,CDocManager类维护一个CPtrList类型的链表m_templateList(即文档模板链表,实际上,MFC的设计者在MFC的实现中大量使用了链表这种数据结构),CPtrList类型定义为:
class CPtrList : public CObject { DECLARE_DYNAMIC(CPtrList)
protected: struct CNode { CNode* pNext; CNode* pPrev; void* data; }; public:
// Construction CPtrList(int nBlockSize = 10);
// Attributes (head and tail) // count of elements int GetCount() const; BOOL IsEmpty() const;
// peek at head or tail void*& GetHead(); void* GetHead() const; void*& GetTail(); void* GetTail() const;
// Operations // get head or tail (and remove it) - don't call on empty list! void* RemoveHead(); void* RemoveTail();
// add before head or after tail POSITION AddHead(void* newElement); POSITION AddTail(void* newElement);
// add another list of elements before head or after tail void AddHead(CPtrList* pNewList); void AddTail(CPtrList* pNewList);
// remove all elements void RemoveAll();
// iteration POSITION GetHeadPosition() const; POSITION GetTailPosition() const; void*& GetNext(POSITION& rPosition); // return *Position++ void* GetNext(POSITION& rPosition) const; // return *Position++ void*& GetPrev(POSITION& rPosition); // return *Position-- void* GetPrev(POSITION& rPosition) const; // return *Position--
// getting/modifying an element at a given position void*& GetAt(POSITION position); void* GetAt(POSITION position) const; void SetAt(POSITION pos, void* newElement);
void RemoveAt(POSITION position);
// inserting before or after a given position POSITION InsertBefore(POSITION position, void* newElement); POSITION InsertAfter(POSITION position, void* newElement);
// helper functions (note: O(n) speed) POSITION Find(void* 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: ~CPtrList(); #ifdef _DEBUG void Dump(CDumpContext&) const; void AssertValid() const; #endif // local typedefs for class templates typedef void* BASE_TYPE; typedef void* BASE_ARG_TYPE; }; 很显然,CPtrList是对链表结构体 struct CNode { CNode* pNext; CNode* pPrev; void* data; }; |
本身及其GetNext、GetPrev、GetAt、SetAt、RemoveAt、InsertBefore、InsertAfter、Find、FindIndex等各种操作的封装。
作为一个抽象的链表类型,CPtrList并未定义其中节点的具体类型,而以一个void指针(struct CNode 中的void* data)巧妙地实现了链表节点成员具体类型的"模板"化。很显然,在Visual
C++6.0开发的年代,C++语言所具有的语法特征"模板"仍然没有得到广泛的应用。
而CDocManager类的成员函数
virtual void AddDocTemplate(CDocTemplate* pTemplate); virtual POSITION GetFirstDocTemplatePosition() const; virtual CDocTemplate* GetNextDocTemplate(POSITION& pos) const; |
则完成对m_TemplateList链表的添加及遍历操作的封装,我们来看看这三个函数的源代码:
void CDocManager::AddDocTemplate(CDocTemplate* pTemplate) { if (pTemplate == NULL) { if (pStaticList != NULL) { POSITION pos = pStaticList->GetHeadPosition(); while (pos != NULL) { CDocTemplate* pTemplate = (CDocTemplate*)pStaticList->GetNext(pos); AddDocTemplate(pTemplate); } delete pStaticList; pStaticList = NULL; } bStaticInit = FALSE; } else { ASSERT_VALID(pTemplate); ASSERT(m_templateList.Find(pTemplate, NULL) == NULL);// must not be in list pTemplate->LoadTemplate(); m_templateList.AddTail(pTemplate); } } POSITION CDocManager::GetFirstDocTemplatePosition() const { return m_templateList.GetHeadPosition(); } CDocTemplate* CDocManager::GetNextDocTemplate(POSITION& pos) const { return (CDocTemplate*)m_templateList.GetNext(pos); |