MFC 单文档的全局变量

转自http://blog.csdn.net/abcjennifer/article/details/7477896

单文档中每个view类中有自己的局部变量,所以在应用程序中定义全局变量要在这些View类啊,Doc类啊的外面。

待解决问题:希望对每处理一个文件,全局变量+1(如图1所示,期望处理后结果为5,CVMFC1不算)


ok,问题实际上是MFC中如何设置和操作全局变量


首先我们讲下最简单的解决方案,后面在分析下MFC原理(*^__^*) 

======================================================================


最简单的解决方案:

1. CXXXApp类(CXXX.h文件)中添加变量,即定义全局变量(也就是累加器)m_ins_num;一般其构造函数会自动赋0

2. 在定义处前面加上 public: 否则会被视为protected属性

3. 在每个View类中调用,在处理函数(如打开函数)中现货区CXXXApp类指针,然后将该属性+1,这里还可以用Messagebox显示数字(整型数)

[cpp]  view plain copy
  1. CCVMFCApp* app=(CCVMFCApp*) AfxGetApp();  
  2.     app->m_ins_num++;  
  3.     char ss[25];  
  4.     sprintf(ss,"num=%d",app->m_ins_num);  
  5.     MessageBox(ss,"instance_num");  

======================================================================

下面讲一下原理什么的

我在编程的时候也经常遇到一些错误:

gj.obj : error LNK2001: 无法解析的外部符号 "int gg" (?gg@@3HA) 
gjDlg.obj : error LNK2001: 无法解析的外部符号 "public: static int CgjApp::g_gl" (?g_gl@CgjApp@@2HA) 
Debug/gj.exe : fatal error LNK1120: 2 个无法解析的外部命令

这些错误是由于对类中见的变量访问造成的,要分清楚是类的静态变量还是对象的成员变量,这很重要哦。

用MFC制作的工程由很多文件构成,它不能象一般C++程序那样随意在类外定义全局变量,在这里要想定义能被工程内多个文件共享的全局变量和函数必须用一些特殊方法才行。实际上有多种方法可以实现,这里只介绍两种方法。 

一、在应用程序类中定义 

用MFC生成的工程中都有一个名为CxxxApp的类,它派生于CWinApp类。这个类主要进行程序的初始化,生成文档、视图对象等工作。我们可以把需要全局访问的变量和函数定义为这个类的成员变量和成员函数,就可以实现全局访问了。 

从严格意义上讲,这种变量和函数并不是全局的,因为它仍然只是类中的成员,只是由于我们很容易获得CxxxApp类的指针,所以我们可以在文档、视图、对话框以及各种自定义类中访问到它们,达到与全局变量类似的效果。访问时用函数“AfxGetApp()”获得CxxxApp类的指针,用“AfxGetApp()->成员”访问变量或函数。 

例: 

Test.h:(应用程序类头文件) 

class CTestApp : public CWinApp 

public: 
int x; //全局变量 
int f(int y); //全局函数 
………… 
}; 

Test.cpp:(应用程序类程序文件) 

int CTestApp::f(int y) //全局函数定义 

y++; 
return y; 


定义在CTestApp类中的变量和函数可以在其它类中被访问。比如在视图的某函数中要访问变量x和函数f(): 

void CTestView::xyz() 

CTestApp *app = (CTestApp *)AfxGetApp(); //生成指向应用程序类的指针 
app->x = 0; //访问变量x 
int z = app->f(1); //访问函数f() 
………… 


这样,变量x和函数f()可以视作为全局的。 

用这种方法实现的全局变量和全局函数虽比较简单,但也有缺点,一是访问不太方便,每次都需要获取应用程序类的指针;再就是把一些与应用程序类本身无关的变量和函数放在里面,使这个类看上去怪怪的,破坏了类的封装。 

二、用静态变量和静态函数实现 

很喜欢API函数的那种调用方法,不论在哪个类中只要用“::API函数”就可以调用了。合理利用静态类型(static)可以实现与此相似的全局变量和全局函数。 

静态变量和静态函数有如下性质: 

若在一个类中用关键字static声明数据成员,则这个数据成员就只存在一个拷贝,无论该类创建了多少个实例,它始终只存在一个,即使该类的实例一个也没创建,它也存在。 

若在一个类中用关键字static声明函数,该函数可以用“类名::函数名”方式访问,无需引用该类的实例,甚至这个类的实例可以不存在。 

利用这个性质实现的全局变量和函数使用起来很方便。 

值得注意的是,全局变量和全局函数最好集中封装,不要在文档、视图等类内部定义,这样用起来才有全局的感觉。 

例: 

1、添加一个没有基类的新类,设类名起为CPublic,姑且称之为公用类 

单击“Insert”菜单下的“New Class”命令,选择“Class type”为“Generic Class”,在“Name”栏中填入类名“CPublic”,单击“OK”,则新类建立完毕。 

2、包含公用类的头文件,使各个类都能访问它 

CPublic的头文件应包含在应用程序类的头文件中,这样在其它类中引用CPublic类时就不需要再包含了。 

Test.h:(应用程序类头文件) 

#include "Public.h" //包含公用类头文件 

class CTestApp : public CWinApp 

………… 
}; 

3、在公用类中定义全局变量和全局函数,均使用static修饰,静态变量还必须在类外定义和初始化 

Public.h:(公用类头文件) 

class CPublic 

public: 
CPublic(); 
virtual ~CPublic(); 

public: 
static int x; //全局变量 
static int time; //全局变量 
static int f(int y); //全局函数 
………… 


在公用类中对静态变量进行初始化和定义函数体: 

Public.cpp:(公用类程序文件) 

int CPublic::x = 0; //初始化全局变量 
int CPublic::time; //定义全局变量 

CPublic::CPublic() 




CPublic::~CPublic() 




int CPublic::f(int y) //全局函数,这里不要再加static 

y++; 
return y; 


4、全局量的使用 

使用变量:CPublic::变量名 

使用函数:CPublic::函数() 

如在视图的某函数中访问变量x和函数f(): 

void CTestView::xyz() 

CPublic::x = 0; //访问变量x 
CPublic::time = CPublic::f(1); //访问函数f() 
………… 


在其它类中访问x、time和f()的方法与此相同。 

5、几点注意: 

① 由于静态量可独立于类存在,不需要生成CPublic类的实例。 

② 静态数据成员的定义和初始化必须在类外进行,如例中x的初始化;变量time虽然没有初始化,但也必须在类外进行定义。由于没有生成CPublic类的实例,所以它的构造函数和析构函数都不会被执行,在里面做什么工作都没有什么意义。 

③ 如果静态函数需要访问CPublic类内的变量,这些变量也必须为静态的。因为非静态量在不生成实例时都不会存在。 如: 

class CPublic 

public: 
int x; //内部变量 
static int f(int y) //全局函数 

x++; 
return x; 
}; 
………… 
}; 

这里x虽为类内成员,但如果不生成CPublic类的实例,就会出现函数f()存在,而变量x不存在的问题。 

总之,用没有实例的类管理全局量是一个不错的选择,它具有集中管理,使用方便的好处。当然,除非特别必要,全局量还是少用为好,一个好的编程者决不会随意滥用全局量的,一个封装做得不好的程序,在修改维护时会让你吃足苦头。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值