拿一个最简单的MFC的例子来看这个问题。
#include <afxwin.h>
class CHelloFrame:public CFrameWnd
{
public:
CHelloFrame()
{
Create(NULL,"Hello World!");
}
};
class CHelloApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
BOOL CHelloApp::InitInstance()
{
m_pMainWnd=new CHelloFrame();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
CHelloApp HelloApp;//请注意这一行。
上面这个程序是没有任何的问题的。
但是如果我们把最后一行给注释掉,那么会怎样呢?
我们编译连接都没有问题。但在执行的时候就会发现问题。
此时,调试器会弹出一个对话框,提示我们下面的信息
这里我们可以点击忽略,然后再弹出的对话框中点击“取消”以进入调试状态
之后会弹出这个提示信息:
点击“确定”按钮,我们会进入调试状态。
这时,我们会看到执行光标会停在winmain.cpp文件中的34行。也就是上面第一个对话框中所指出的一个错误。我们把鼠标停在pApp指针变量上,这时会发现它的值为0x00000000。也就是NULL。这说明什么呢?程序没有一个应用程序实例。
这里我们有人会问,WinMain.cpp文件中的ASSERT_VALID的作用是什么?我们可以在msdn中查到下面的信息:
ASSERT_VALID
ASSERT_VALID( pObject )
Parameters
pObject Specifies an object of a class derived from CObject that has an overriding version of the AssertValid member function.
Remarks
Use to test your assumptions about the validity of an object's internal state. ASSERT_VALID calls the AssertValid member function of the object passed as its argument.
In the Release version of MFC, ASSERT_VALID does nothing. In the Debug version, it validates the pointer, checks against NULL, and calls the object's own AssertValid member functions. If any of these tests fails, this displays an alert message in the same manner as ASSERT.
简单的翻译如下:
ASSERT_VALID( pObject )
参数:
pObject 制定一个由CObject派生出来的类。在 CObject中有一个AssertValid成员函数的可以覆盖(overriding)的版本
说明:
用来测试你的有关一个对象的内部状态的假设。宏ASSERT_VALID 会调用作为参数传递过来的对象的AssertValid成员函数。在MFC的发行(Release),ASSERT_VALID 版本中,宏ASSERT_VALID不会做任何事情。但在Debug 版本中,它要检查这个指针的有效性,看其是否为NULL,并调用这个对象本身的AssertValid成员函数。 如果测试失败,就会象ASSERT一样显示警告信息。