在App中InitInstance()里, CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_SMSTYPE,
RUNTIME_CLASS(CMYDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CMYView));
AddDocTemplate(pDocTemplate);这个pDocTemplate系统是在哪里delete的?如果自己加了一个template,要在哪里delete?
pMyDocTemplate = new CMultiDocTemplate(
IDR_SMSTYPE,
RUNTIME_CLASS(CMYDoc1),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CMYView1));如果自己的函数中打开文档
m_pDoc = pTemplate->OpenDocumentFile(NULL);
要不要做delete工作?是不是pTemplate删除了,doc就自动删除了?

解决方案 »

  1.   

    不用把,CWinApp::AddDocTemplate 调用 CDocManager::AddDocTemplate , 程序终止时 CWinApp::~CWinApp 负责 delete 拥有的 CDocManager ,然后 CDocManager::~CDocManager 会负责 delete 所有拥有的 DocTemplate ...
      

  2.   

    doctemplate是由CDocManager管理的,这是CDocManager的析构函数:
    CDocManager::~CDocManager()
    {
    // for cleanup - delete all document templates
    POSITION pos = m_templateList.GetHeadPosition();
    while (pos != NULL)
    {
    POSITION posTemplate = pos;
    CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
    if (pTemplate->m_bAutoDelete)
    {
    m_templateList.RemoveAt(posTemplate);
    delete (CDocTemplate*)pTemplate;
    }
    }
    }
    从上面可以看出,只要你的doctemplate在创建的时候设置m_bAutoDelete为true,那么在CDocManger析构的时候会自动删除,否则要你自己delete。
       以上只是在你调用了AddDocTemplate把template交给docmanager的情况下讨论的。如果你没有调用AddDocTemplate,那么模板要你自己删除。
      

  3.   

    如果是没有通过 AddDocTemplate 注册的 DocTemplate ,恐怕需要自己在 CWinApp::~CWinApp 中 CloseAllDocuments() 并 delete
      

  4.   

    CDocTemplate::CloseAllDocument() 通过调用 CDocument::OnCloseDocument 清除所有打开的文档,从 OnCloseDocument 的代码中可以看见这个函数关闭了所有 ChildFrame / View , 并 delete this 
      

  5.   

    不需要自己删除!
    标准的CWinApp的析构函数负责删除这些对象
      

  6.   

    我错了...更正,psusong(在黑夜中寂寞成长的橡树) 说的对,都不需要显式的 deleteCDocTemplate::CDocTemplate 会自动的在 static 表 CDocManager::pStaticList 中添加自己,如果 AddDocTemplate 被调用,CDocManager 会收集所有在 pStaticList 中的 DocTemplate,无论怎样,pStaticList 和 CDocManager 都会在 CWinApp::~CWinApp 中清除,并 delete 所有的 DocTemplate
      

  7.   

    to In355Hz(好象一条狗):
       你说的是CDocTemplate的构造函数。而楼主问的是CMultiDocTemplate。CMultiDocTemplate的构造函数是不会去创建CDocManager::pStaticList,再把自己加到里面去的。所以如果new一个CMultiDocTemplate而不调用AddDocTemplate,最后必须要delete,否则就会内存汇漏。在MFC中调试一下就可以证明这一点。
      

  8.   

    前几天出差了。多谢这么多大侠来捧场。看了一下楼上的,发现不管有没有AddDocTemplate(pDocTemplate);标准的CWinApp的析构函数都会删除这些对象。CWinApp::~CWinApp()
    {
    // free doc manager
    if (m_pDocManager != NULL)
    delete m_pDocManager; // free recent file list
    if (m_pRecentFileList != NULL)
    delete m_pRecentFileList; // free static list of document templates
    if (!afxContextIsDLL)
    {
    if (CDocManager::pStaticList != NULL)
    {
    delete CDocManager::pStaticList;
    CDocManager::pStaticList = NULL;
    }
    if (CDocManager::pStaticDocManager != NULL)
    {
    delete CDocManager::pStaticDocManager;
    CDocManager::pStaticDocManager = NULL;
    }
    }
    ......
    }class CDocManager : public CObject
    {
    .....
    public:
    static CPtrList* pStaticList;       // for static CDocTemplate objects
    static BOOL bStaticInit;            // TRUE during static initialization
    static CDocManager* pStaticDocManager;  // for static CDocTemplate objects
    ...
    }
      

  9.   

    CDocTemplate::CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
    CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
    {
    ....
    / add to pStaticList if constructed as static instead of on heap
    if (CDocManager::bStaticInit)
    {
    m_bAutoDelete = FALSE;
    if (CDocManager::pStaticList == NULL)
    CDocManager::pStaticList = new CPtrList;
    if (CDocManager::pStaticDocManager == NULL)
    CDocManager::pStaticDocManager = new CDocManager;
    CDocManager::pStaticList->AddTail(this);
    }
    else
    {
    m_bAutoDelete = TRUE;   // usually allocated on the heap
    LoadTemplate();
    }
    }to webber84(***闭关修炼中***) :CMultiDocTemplate是CDocTemplate的派生类,所以new一个CMultiDocTemplate,应该是先执行CDocTemplate的构造函数,再执行CMultiDocTemplate的构造函数。会自动的在 static 表 CDocManager::pStaticList 中添加自己。以上是我的理解,不知道正确已否。请大家继续发表意见。
      

  10.   

    至于m_pDoc = pTemplate->OpenDocumentFile(NULL);
    要不要做delete工作?
     In355Hz(好象一条狗) ( ) 信誉:110  2003-03-27 17:43:00  得分:0 
     
     
      CDocTemplate::CloseAllDocument() 通过调用 CDocument::OnCloseDocument 清除所有打开的文档,从 OnCloseDocument 的代码中可以看见这个函数关闭了所有 ChildFrame / View , 并 delete this 这是正确的。下面是我查到的。
    文档何时被析构? 在SDI程序中,程序退出后文档就被删除。在MDI程序中,与该文档相关的最后一个视图关闭时文档就被删除。CView::~CView()
    {
    if (m_pDocument != NULL)
    m_pDocument->RemoveView(this);
    }void CDocument::RemoveView(CView* pView)
    {
    ASSERT_VALID(pView);
    ASSERT(pView->m_pDocument == this); // must be attached to us m_viewList.RemoveAt(m_viewList.Find(pView));
    pView->m_pDocument = NULL; OnChangedViewList();    // must be the last thing done to the document
    }void CDocument::OnChangedViewList()
    {
    // if no more views on the document, delete ourself
    // not called if directly closing the document or terminating the app
    if (m_viewList.IsEmpty() && m_bAutoDelete)
    {
    OnCloseDocument();//这里就执行了In355Hz所说的函数了。
    return;
    } // update the frame counts as needed
    UpdateFrameCounts();
    }void CDocument::OnCloseDocument()
    // must close all views now (no prompting) - usually destroys this
    {
    // destroy all frames viewing this document
    // the last destroy may destroy us
    BOOL bAutoDelete = m_bAutoDelete;
    m_bAutoDelete = FALSE;  // don't destroy document while closing views
    while (!m_viewList.IsEmpty())
    {
    // get frame attached to the view
    CView* pView = (CView*)m_viewList.GetHead();
    ASSERT_VALID(pView);
    CFrameWnd* pFrame = pView->GetParentFrame();
    ASSERT_VALID(pFrame); // and close it
    PreCloseFrame(pFrame);
    pFrame->DestroyWindow();
    // will destroy the view as well
    }
    m_bAutoDelete = bAutoDelete; // clean up contents of document before destroying the document itself
    DeleteContents(); // delete the document if necessary
    if (m_bAutoDelete)
    delete this;//这里就删除CDocument*指针了。
    }
    }
      

  11.   

    to 52001314(生命在于运动):
       
        那天回贴太仓促,的确犯了你说的错误。今天仔细看了一下MFC的源码,得出的结果还是必须自己deleteCDocManager类有这么几个静态成员: 
    class CDocManager : public CObject
    {
    public:
         static CPtrList* pStaticList;     // for static CDocTemplate objects
         static BOOL bStaticInit;          // TRUE during static initialization
         static CDocManager* pStaticDocManager;  // for static CDocTemplate objects
    }
    相信你也看到MFC开发人员的注释,这些都是给静态的CDoctemplate对象准备的。这三个成员分别被初始化为TRUE,NULL,NULL。然后你看CWinApp的InitApplication函数:
    BOOL CWinApp::InitApplication()
    {
    if (CDocManager::pStaticDocManager != NULL)
    {
    if (m_pDocManager == NULL)
    m_pDocManager = CDocManager::pStaticDocManager;
    CDocManager::pStaticDocManager = NULL;
    } if (m_pDocManager != NULL)
    m_pDocManager->AddDocTemplate(NULL);
    else
    CDocManager::bStaticInit = FALSE;
             return TRUE;
    }
    如果CDocManager::pStaticDocManager!=NULL,那么 m_pDocManager被指向pStaticDocManager。但是pStaticDocManager是被初始化为NULL的,只有一个地方可以改变它的值,就是在CDocTemplate的构造函数中:
    CDocTemplate::CDocTemplate()
    {
        ………………
        if (CDocManager::bStaticInit)
        {
               if (CDocManager::pStaticList == NULL)
                  CDocManager::pStaticList = new CPtrList;
               if (CDocManager::pStaticDocManager == NULL)
                  CDocManager::pStaticDocManager = new CDocManager;
               CDocManager::pStaticList->AddTail(this);
         }
    }
    注意只有一种情况下CDocTemplate的构造函数会先InitApplication执行,那就是你定义了一个全局的CDocTemplate对象。除些以外,InitApplication执行时CDocManager::pStaticDocManager必定为NULL。而此时CWinApp::m_pDocManager也是为NULL的,于是CDocManager::bStaticInit就在InitApplication被设为了false. 从前面列出的CDocTemplate的构造函数可以看到,只有在CDocManager::bStaticInit为TRUE的情况下,对象才会被加到CDocManager::pStaticList中。
       
        从上面的执行情况说明,如果你new了一个CDocTemplate对象而没有调用AddDocTemplate,就必须自己delete,否则就有内存泄漏。这一点我已经在MFC中验证过了。
      

  12.   

    谢谢 webber84(***闭关修炼中***) 我觉得你是正确的。不过如果这样的话,我们平时的SDI,MDI中,CDocManager::pStaticList应该都是NULL了?不知道其他大侠还有什么见解吗?
      

  13.   

    我也同意 webber84(***闭关修炼中***) 的看法,记得那天我也注意了 bStaticInit ,但是没有看到何时 bStaticInit = FALSE
      

  14.   

    非常感谢webber84(***闭关修炼中***) 和In355Hz(好象一条狗)结贴了。如果有人有不同意见,请继续发表。