变量的作用功能、作用域和作用形态

来源:互联网 发布:推荐几家les淘宝店 编辑:程序博客网 时间:2024/03/28 18:10

1.变量的作用功能 Function of variables 

    整体上讲,变量分为存储服务两种类型。

    前者如CPeople *p=new CPeople(),其特点是与客观对象一一对应,其数量一般较大,而且应与客观对象的生存期相同。

    后者如COODBDatabase Db,其特点是为了完成某个功能出现,数量以能完成功能为限(经常是一个),生存期可以只是本功能的执行时间;不过为了方便,避免多次定义,往往可超过此周期。

    因此,如果一个类需要被声明大量实例,那么不要在其中声明用于服务的成员变量(至少不要声明那些大的),用以下方法来调用服务:

  • 声明static的成员变量,使所有实例共用一个变量;
  • 在成员函数实现中声明所需的服务,不过如果服务是一个需要构造和析构的类,会引起速度下降;
  • 引用外部服务类的指针;

    Variables can be divided mainly into two types: for storage and for service.

    Sample for storage is CPeople *p=new CPeople(), its characteristic is that it is corresponding to a real object, and the amount of this type of variable maybe large, it exists as long as the real object need. 

    Sample for service is COODBDatabase Db, its characteristic is that it exists for only a function, the amount of this type of variable is decided by the function requirement and it lives only during the function; but for convenience and avoiding repeated definition, some can outlive the function.

    So if a class will be instanced for a large number, 

    

1.2 变量的作用域 Life area?? of variables 

全局变量

    大部分程序可以不用任何全局变量完成其功能,因此应当不使用全局变量。但在以下情况下,可方便且安全地使用全局变量:

    ①此变量类型只声明唯一的实例,并且生存期与进程相同:

  • 主窗口或主进程:如extern CFhtHostApp theApp; extern CFhtHostDlg *g_pDlg;其命名不需要很具体;
  • 全程唯一此类型的实例:如CMyCAHost *g_pMyCAHost; COODBDatabase COODBDatabase::m_DefaultOODBDatabase;

如果需要声明两个以上实例的,则按规范以g_开头,且命名要具体,以示区别。

    ②非VC++类的函数,且需要符合其特定参数的,可用全局变量进行传递:

  • Rpc的实现函数,如:

extern "C" boolean RpcSetHost(handle_t IDL_handle,int *pnSize,unsigned char *szCAHost)
    {
    ...
    g_CAConsole.SetHost(pCAHost); 
    ...
    }

  • 线程函数,如:

DWORD WINAPI CRpcServer::ServerThread(LPVOID pParam)
    {
    ...
    g_pServer->StopServer();
    ...
    }

    注意,配合全局函数使用,可提高全局变量的稳定性。

    CADPS系统中的::FhtLoadConfig()函数实际上调用了全局变量CCARegistry::g_CARegistry,使用全局函数屏蔽了全局变量,将此全局变量的应用局限在全局函数内部,因而只需此类的管理员保证此函数中的应用是安全的,对此函数的调用也都是安全的。

    利用全局函数封装全局变量的好处与类的封装相似。在《设计模式》一书中提到的可复用面向对象编程的第一个原则就是:针对接口编程,而不是针对实现编程。这样在需要改变数据结构时,应用层的软件可以完全不改动。

    将无谓的全局变量转换为其他变量,可提高系统稳定性。

类成员变量

    类的成员变量用以存储类的数据、状态、外部数据或服务的地址。以下是一些关于成员变量应用适当和不当的场合:

    ①绝大部分用成员变量进行服务的场合都可以通过其他方法化解,从而使成员变量只有存储功能。

    例如COODBRecord中的CTypedPtrArray <CObArray,COODBField*> m_FieldArray变量,尽管从自然对象中抽象时,每个记录都包含多个Field,而且数据也存储在Field中,但实际上在C++类中,数据是存储在其相应的变量中的,COODBField只在GetFieldValue()函数调用时用一次将数据库中的数据取出,然后用COODBField::DatabaseToClass()转换为C++数据类型,并将数据赋值给C++变量的地址,因而是服务型数据,所以后来将其取消,而在GetFieldValue()调用时生成一组(和列数相同)临时的数据,进行转换服务,将每次Select()操作时所需COODBField的数量从300000(20000Customers时)个减少到15个,将内存占用从107M减少到55M,还节约了运行时间。

    实际上在上例中,只需要一个而非一组COODBField即可完成此工作,不过由于程序易读性比效率更优先,所以在影响不大的情况下(15个和1个内存占用差别不大),并不考虑优化效率的极端手段。

    如果用于服务的数据很小,不适合单独在类的外部声明,则可以改为该服务函数中的一个临时变量。但有些数据的构造和销毁相当花费时间(如CString/CDBVariant等),这时候可考虑将此数据声明为类的static变量。相关内容

    ②绝大部分以上使用场合以外的全局变量,都可以被一个类成员变量以外部服务地址的方式取代。

    在COODBQuery中有一个变量COODBCDMap *m_cpOODBCDMap,此数据存储了全局变量COODBCDMaps g_OODBCDMaps中与此类相对应的列与变量地址的映射信息,由于使用了一个变量来存储此映射信息的地址,并在COODBQuery调用m_cpOODBCDMap=::FhtOODBCDMapOf(aClass.CDMapName())来初始化此变量,而不是直接使用全局变量。因而因而在此后的操作中将不再需要用到全局变量,而只需要判断m_cpOODBCDMap的合法性即可。

类函数变量,全局函数变量

    (略)

1.3 变量作用形态 State of variables 

静态变量

    因为在程序运行时只使用同一个实例,因而可以节约其构造器和销毁器的运行时间,对海量运算节约时间有益。常见的构造器和销毁器缓慢的类包括CString,COle系列类等。要特别注意的是静态变量的声明初始化如static int nCount=0;只进行一次,因此这种应用中要特别注意清除上次的参数数据或避免其影响。

    静态变量的一种常见应用是用来记录上次运行时的数据,不过从经验来看,如果是在类的函数中,应直接声明此数据为类的变量可使应用更加易于理解和控制。