C++静态变量对象的建立和删除,兼论MFC开始运行的起点(全局对象)
看了不少C++书,当讲到静态变量的时候,总是以int成员来举例,是啊,这样很好理解。但是如果这个静态变量是一个对象行不行呢?不仅行,有时候还非常必要,而且别有洞天。
比如:
// .h 文件
class SystemGlobal
{
public:
static ConfigXML* m_pInstance;
}
// .cpp 文件
ConfigXML* SystemGlobal::m_pInstance = new ConfigXML();
SystemGlobal::SystemGlobal(void)
{
}
那么应该何时删除这个对象呢?想了很久,一开始觉得应该是在main()函数里,我这是还是QT程序,不得不改写了main()函数通常的return 方式,变成这样:
MainWidget main_widget;
main_widget.showWidget(); int ret = app.exec();
delete SystemGlobal::m_pInstance;
return ret;
我试了试,程序可以正常退出。反正我试了5遍都没有问题。普通C++程序没有app.exec的困扰,应该更加没有问题。
---------------------------------------------------------
然后我又在网上搜了搜(很难搜到啊),受这个帖子启发:
http://bbs.csdn.net/topics/200006181
改成在拥有静态变量对象的类析构函数里删除它,如下:
SystemGlobal::~SystemGlobal(void)
{
delete SystemGlobal::m_pInstance;
}
同样试了5次,也没有问题。
但是我觉得这种方法不好,因为万一SystemGlobal在整个项目中有多个实例呢,难道销毁一个实例的时候,就必须销毁这个静态对象?这种方法只适合于整个项目就这一个SystemGlobal实例的情况。而且析构函数不允许重载和参数,就显得更加有问题了。
---------------------------------------------------------
最后要提一句,静态变量对象的初始化不仅仅别有洞天,而且实际上是相当重要的,因为它会在main()函数开始前执行,这代表什么?代表在main()函数的第一句语句执行之前,已经执行过这个静态变量对应的类的构造函数了,而构造函数本身可以执行无穷无尽的语句,相当于main()函数只是一个正房,在正房出现前,程序员已经与小三天翻地覆一番后才回来了(真是经典案例!),而且这个小三仍存在于内存之中,与正房并列。
不要奇怪,其实MFC的执行流程就是从CMyApp(继承于CWinApp)的theApp实例生成的过程开始的(注意,theApp不是静态变量对象,但却是一个写在.cpp文件中的全局对象,其实与静态变量对象也没有什么本质的区别,也正因为theApp对象的指针仍需要被获取,但又没有静态变量那么方便,所以微软专门提供了AfxGetApp()全局函数。但是为什么提供这个函数,而不是使用静态变量对象呢?我觉得2个原因,1是静态变量名称又臭又长,2是函数具有更好的封装性,可以做更多的检查乃至偷天换日):
MyApp::MyApp()
{ // 断点2,在括号这行下断点
} MyApp theApp; // 断点1,在这行也下断点 BOOL MyApp::InitInstance()
{
}
// 断点3,手动打开appmodul.cpp文件,然后在_tWinMain的括号处下断点
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,__in LPTSTR lpCmdLine, int nCmdShow)
{
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
执行,通过追踪MFC源代码,可以发现程序首先定位于断点1,按F11追踪,发现会落在断点2。继续按F11,会发现执行CWinApp::CWinApp(LPCTSTR lpszAppName),然后按F10,发现会执行一大堆语句才会返回。可见的确实别有洞天。做完这些事情以后,就开始执行WinMain函数了(断点3),具体可以发现WinMain函数是在appmodul.cpp文件中。
读书笔记,两种效果:1. 在MFC初始化完成后,WinMain被自动调用,两者就相互联系起来了 2. MFC没有也不可能封装WinMain函数(有待进一步阐述)
参考:
http://www.cnblogs.com/zhili/p/mfcanalyze.html
http://www.moon-soft.com/program/bbs/readelite9623.htm
http://www.cnblogs.com/suncoolcat/p/3367627.html
http://www.xuebuyuan.com/2119787.html (彩色贴图,比较清楚)
http://cnmqw.iteye.com/blog/1921782 (精简了代码,非常清楚)
C++静态变量对象的建立和删除,兼论MFC开始运行的起点(全局对象)的更多相关文章
- 全局对象Application的使用,以及如何在任何地方得到Application全局对象
Application和Activity,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个application对象,用来存储系统的一些信息.通常我们是不 ...
- Java 局部变量、实例变量、类变量(静态变量)区别
1. 局部变量: 局部变量是类的方法中的变量: 2. 实例变量: 实例变量也是类中独立于方法之外的变量,不过没有static修饰,也叫 对象变量 3. 类变量(静态变量): 类变量是类中独立于方法之外 ...
- [ 转载 ]Java:成员变量,局部变量,静态变量的区别
精简后方便自己理解. 成员变量 我们研究一个事物: 属性:外在特征:如身高,体重 行为:能做什么:如说话,打球. 在Java语言中,最基本的单位是类(class),类就是用来体现事物的. 属性:类中的 ...
- 1.7Oob 静态变量静态方法
1)静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员 2)如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问非静态变量. 3)静态方法中不能直接调用非静态方法 ...
- 成员变量(实例变量)&局部变量&静态变量(类变量)的区别
成员变量(实例变量)&局部变量区别: (1)作用域 成员变量:针对整个类有效. 局部变量:只在某个范围内有效.(一般指的就是方法,语句体内) (2)存储位置 成员变量:随着对象的创建而存在,随 ...
- 谈谈java中静态变量与静态方法在有继承关系的两个类中调用
谈谈java中静态变量与静态方法在有继承关系的两个类中调用 学习的中如果遇到不明白或者不清楚的的时候,就是自己做些测试,自己去试试,这次我就做一个关于静态变量和静态方法在有继承关系的两个类中的问题测试 ...
- java 静态变量&静态方法
1. 静态变量是static修饰的成员变量(类变量),若无static修饰,则是实例变量.静态变量是一种全局变量,它属于某个类,不属于某个对象实例,是在各对象实例间共存. 访问静态变量直接通过类名 ...
- JavaScript中hoisting(悬置/置顶解析/预解析) 实例解释,全局对象,隐含的全局概念
JavaScript中hoisting(悬置/置顶解析/预解析) 实例解释,全局对象,隐含的全局概念 <html> <body> <script type="t ...
- JavaScript 全局对象
全局属性和函数可用于所有内建的 JavaScript 对象. 顶层函数(全局函数) 函数 描述 decodeURI() 解码某个编码的 URI. decodeURIComponent() 解码一个编码 ...
随机推荐
- day-3
/* 快noip了!!!感觉还有好多事要做 上午考试 原题没做 自己找了套题 挺水的 T1模拟(然而没认真读题 90) T2 dp+简单优化 数据有点问题 T3 暴力状丫 然而写丑了 60分的要两秒多 ...
- 利用php给图片添加文字水印--面向对象与面向过程俩种方法的实现
1: 面向过程的编写方法 //指定图片路径 $src = '001.png'; //获取图片信息 $info = getimagesize($src); //获取图片扩展名 $type = image ...
- eclipse 好用的快捷键
Ctrl+Shift+X 把当前选中的文本全部变味小写 Ctrl+Shift+Y 把当前选中的文本全部变为小写 Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定) ...
- 周末充电之WPF(二 ) .窗口的布局
登录窗口布局:[ Grid 布局 -Grid.RowDefinitions / Grid.ColumnDefinitions] 代码如下: <Window x:Class="login ...
- javascript调用oc的方法
1.引入#import <JavaScriptCore/JavaScriptCore.h> 2.JSContext *jsContext = [self.webView valueForK ...
- [转]Javascript 严格模式详解
原文地址:http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mode.html 一.概述 除了正常运行模式,ECMAscript 5添加 ...
- UVA 10066 The Twin Towers(LCS)
Problem B The Twin Towers Input: standard input Output: standard output Once upon a time, in an anci ...
- 高效的VS调试技巧
本文总结了十个调试技巧,当你使用VS的时候可以节省你很多时间. 1.悬停鼠标查看表达式 调试有时候很有挑战性,当你步入一个函数想看看哪块出错的时候,查看调用栈来想想值是从哪来的.另一些情况下,则需要添 ...
- H5小内容(六)
Web Worker 基本内容 单线程与多线程 Worker可以模拟多线程的效果 定义 - 运行在后台的javascript 注意 - 不能使用DOM ...
- js事件流、事件处理程序/事件侦听器
1.事件流 事件冒泡 IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档). 事件捕获 ...