MFC的程序执行顺序

MFC的程序和C语言的程序,从执行原理上说,是完全一致的。

当Windows操作系统启动一个程序时,它调用的就是该程序的WinMain函数(实际是由插入到可执行文件中的启动代码调用的)。WinMain是Windows程序的入口点函数,与DOS程序的入口点函数main的作用相同,当WinMain函数结束或返回时,Windows应用程序结束。

Win32应用程序有一条很明确的主线:首先进入WinMain函数,然后设计窗口类、注册窗口类、产生窗口、注册窗口、显示窗口、更新窗口,最后进入消息循环,将消息路由到窗口过程函数中去处理

WinMain函数是程序的入口函数。也就是说,程序运行时首先应该调用的是WinMain函数,那么这里为什么程序会首先调用CTestApp类的构造函数呢?看一下CTestApp的源文件,可以发现程序中定义了一个CTestApp类型的全局对象:theApp。代码如下。

///

// The one and only CTestApp object

CTestApp theApp;

 MFC的程序执行顺序 - horatio - horatio提示:MFC程序的全局变量都放置在ClassView标签页的Globals分支下,展开该分支即可看到程序当前所有的全局变量。双击某个全局变量,即可定位到该变量的定义处。应该明白了先前穿件的Test程序的运行顺序,也就是为什么全局变量的theApp的构造函数会在WinMain函数之前执行了。

那么为什么要定义一个全局对象theApp,让它在WinMain函数之前执行呢?该对象的作用是什么?

 理论:无论是全局变量,还是全局对象,程序在运行时,在加载main函数之前,就已经为全局变量或全局对象分配了内存空间。对一个全局对象来说,此时就会调用该对象的构造函数,构造该对象,并进行初始化。
       具体原因是:应用程序的实例是由实例句柄(WinMain函数的参数hInstance)来标识的。而对MFC程序来说,通过产生一个类的对象(CWinApp的对象)来唯一标识应用程序的实例。每一个MFC程序有且仅有一个从应用程序类(CWinApp)派生的类。每一个MFC程序实例有且仅有一个该派生类的实例对象,也就是theApp全局对象。该对象表示了应用程序本身。当一个子类在构造之前会先调用其父类的构造函数。因此,theApp对象的构造函数CTestApp在调用之前,会调用其父类CWinApp的构造函数,从而就把我们程序自己创建的类与Miscrosoft提供的基类关联起来了。CWinApp的构造函数完成程序运行时的一些初始化工作。

我们在这个全局对象定义处设置一个断点,然后调试运行Test程序,将发现程序执行的顺序依次是:

(1)theApp全局对象定义处;

(2)TestApp构造函数;

(3)然后才是WinMain函数。

 

C中的main函数就相当于MFC中的WinMain函数。

感兴趣的可以利用VC的断点设置自己跟踪下面讲述的各个函数,就明白它的执行顺序了。

一、C语言程序执行步骤

在C语言中,大约的步骤如下:

1,   全局变量内存分配 例子如下:

#include <iostream.h>

int a=88;

main(){

cout<<a<<endl;

}

如果我们在main前设置断点,我们就会发现,在进入main之前,a就已经存在了。也就是说像a这样的全局变量在进入main函数前已经创建,并初始化。

2,   进入main函数

二、MFC程序的运行步骤(主要是初始化)

打开一个MFC APPWizard(exe)工程,跟踪其执行步骤,可以发现,是以下顺序:

1)CXXApp中的全局变量定义(在WinMain()函数之前定义的全局变量)

CXXApp theApp;

2)调用CXXApp构造函数(当然,创建一个类,它首先会调用自己的构造函数,这时WinMain()还没有运行呢,呵呵奇怪吧?跟上面例子的变量a,其实是差不多的。)

CXXApp ::CXXApp(){}

3)进入Winmain函数(_tWinMain为宏,值为WinMain)(这个函数不是我们自己写的,而且是隐藏在一个比较隐蔽的文件里面,D:/Program Files/Microsoft Visual Studio/VC98/MFC/src/WINMAIN.CPP里面。)

_tWinMain(){} (如果你查看它的定义,#define _tWinMain      WinMain,其实两者是一样的)

4)完成初始化工作:包括窗口类注册、窗口产生、显示和更新

pThread->InitInstance() (由于InitInstance是虚函数,所以这次调用的是派生类的InitInstance()函数,也就是你能在theApp里面看到的那一个函数)

 

 整个执行都在CXXXApp中,先构造CXXXApp,再调用CXXXApp::InitInstance();主程序结束前调用CXXX::ExitInstance(),然后程序退出。  
          在CXXXApp::InitInstance(),设置主窗口,若主窗口退出,则主程序调用CXXX::ExitInstance(),并退出;若未设置主窗口,则CXXXApp::InitInstance()返回后就调用CXXX::ExitInstance(),并退出。  
          注意,若CXXX::ExitInstance()返回FALSE,则不会调用CXXX::ExitInstance(),直接退出。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值