在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就自动删除了?
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就自动删除了?
解决方案 »
- 怎样对抓来的HTTP数据包进行排序,想要组合成一个完整的包数据
- 怎样保存用cpen在窗体上画的图形
- 有没有多线程编程的模式?
- 音频8位的pcm数据, 如何将unsigned转换成a-law编码,希望搞过这方面的朋友不惜赐教谢谢!
- 关于XtremeToolkit里的Toolbox控件的问题(100分)
- 求救,为什么托盘里的图标只能显示16色,无论我怎么做多少颜色的图标,它还是16色.
- 很简单问题求绝对值用那个函数?
- 在程序中隐式加载了一个DLL之后,使用下面的函数为什么会出错啊???怎么办?急,谢谢大家!
- 请解释一下....
- 如何禁止一个特定的程序的运行?
- 只有lib文件和.h头文件,没有Dll文件,可以调用lib文件么?
- SDI/MDI,,Single/MultiDocTemplate完全辨析,对您绝对有益无害!!!!!!!!!
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,那么模板要你自己删除。
标准的CWinApp的析构函数负责删除这些对象
你说的是CDocTemplate的构造函数。而楼主问的是CMultiDocTemplate。CMultiDocTemplate的构造函数是不会去创建CDocManager::pStaticList,再把自己加到里面去的。所以如果new一个CMultiDocTemplate而不调用AddDocTemplate,最后必须要delete,否则就会内存汇漏。在MFC中调试一下就可以证明这一点。
{
// 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
...
}
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 中添加自己。以上是我的理解,不知道正确已否。请大家继续发表意见。
要不要做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*指针了。
}
}
那天回贴太仓促,的确犯了你说的错误。今天仔细看了一下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中验证过了。