baizy77的个人主页

http://www.qtcn.org/bbs/u/88608  [收藏] [复制]

baizy77

小白

  • 2

    关注

  • 8

    粉丝

  • 1

    访客

  • 等级:新手上路
  • 总积分:0
  • 男,1977-11-27

最后登录:2021-01-06

更多资料

日志

4.2 知识点 使用命名空间

2020-12-24 14:50

本案例对应的源代码目录:src/chapter04/ks04_02。
无论是进行项目研发还是产品研发,都不可避免会碰到重名问题:头文件重名、模块名重名、类或结构体重名、接口重名、全局变量重名等等。对于头文件名重名和模块名重名的情况,软件开发组织需要制定软件研发管理规范进行制度上的约束,而且还要建立专门的组织进行落地管理。解决类重名、接口重名、全局变量重名问题的方法也很简单:使用命名空间进行管理。本节将介绍如何在Qt开发中使用命名空间。
在4.1节介绍了怎样开发一个DLL,本节在4.1节的基础上增加命名空间的使用。一般情况下只为DLL代码设置命名空间,不为EXE代码设置命名空间(当需要把EXE与DLL设置为同一个命名空间时除外)。对于某一个DLL项目,一般也只设置一个命名空间。那么,具体该怎样使用命名空间呢?使用命名空间进行管理一共分为两大步:
(1)在DLL中将代码写到命名空间中。
(2)在其他代码中使用命名空间中的类或接口。
下面进行详细介绍。
1.在DLL中将代码写到命名空间中
在DLL中使用命名空间的语法:

namespace 命名空间名称 {                                                            
   ...
}

将命名空间内的代码写在{}内。请注意命名空间不是类定义,所以{}结束后不写“;”。为DLL选择一个命名空间,本案例使用ns_ks04_02。将DLL的h文件和cpp文件的对外引出类写到命名空间ns_ks04_02中,见代码清单4-9中标号①处。在命名空间结束时不写“;”,见标号②处。建议软件开发组织建立专门的机构并发布“命名空间管理规范”,以便对新增命名空间进行审批、登记。软件开发组织应该只允许使用批准后的命名空间。
代码清单4-9

// myclass.h
#pragma once
#include "ks04_02_export.h"
namespace ns_ks04_02 {                                                            
    class KS04_02_Export CPrint {
        ...
    };
    KS04_02_Export int func1();
    KS04_02_Export int func2(int, float);
}                                                                                

注意:命名空间的保护范围应该仅仅是需要引出的类或接口,因此需要把#include "xxx.h"语句排除在外。如果是类的前向声明语句,那么要区分对待:
  1. 如果不是该DLL中定义的类,需要把它排除在命名空间之外。
  2. 如果是该DLL中定义的类,需要把它包含到命名空间之内。

在DLL的cpp文件中用同样的方式把代码写到命名空间里,如代码清单4-10所示。
代码清单4-10

// myclass.cpp
#include "myclass.h"
...
namespace ns_ks04_02 {
    void CPrint::printOnScreen(const char* szStr)    {
        if (NULL == szStr)
            return;
        cout << szStr << endl;
    }  
    int func1()   {
        return 0;
    }
    ...
}

2.在代码中使用命名空间中的类或接口
在EXE或其他DLL中使用ks04_02_dll中定义的类或接口时,需要使用命名空间。见代码清单4-11。在标号①处、标号②处采用了命名空间的语法,即命名空间名称::类名、命名空间名称::接口名的写法。
代码清单4-11

// main.cpp
...
#include "myclass.h"
int main(int argc, char * argv[]) {
               ...
    ns_ks04_02::CPrint pr;                                                      
    pr.printOnScreen("it is a test!");
    ns_ks04_02::func1();                                                        
    ns_ks04_02::func2(2, 3.f);
    return 0;
}

目前为止,已在DLL中定义了命名空间并在EXE中使用了DLL中的引出类、引出接口。现在说明几点注意事项。
1)不在头文件中使用using namespace xxx这种代码
在头文件中使用using namespace xxx的代码会导致命名空间污染。使用命名空间的示意代码见代码清单4-12。
代码清单4-12

// 推荐的写法
ns_ks04_02::CPrint  printObject;                                                
// 不推荐的写法
using ns_ks04_02::CPrint;                                                        
CPrint printObject;                                                              

推荐使用标号①处的写法,不推荐标号②处的写法。采用标号②处的写法时,标号③处用CPrint定义printObject时就可以不写“ns_ks04_02::”了。但是,如果在同一个文件中包含的其他头文件(属于别的DLL)中也存在另一个叫CPrint(类名相同)的类时,就会有问题了。所以,建议采用ns_ks04_02::CPrint的写法。
2)当需要为EXE项目设置命名空间时,不要把main()函数放到命名空间里
有时候EXE和DLL同属一个大项目,为了方便调用DLL中的类,就会把EXE项目的代码也设置到跟DLL相同的命名空间中。这种情况下应该把main()函数排除在外,否则编译器会认为mian()函数属于命名空间,而不会把它当作正常的main()函数入口(正常的main函数入口应该是全局的),从而导致编译错误。代码清单4-13是无法编译通过的,需要把main()函数从命名空间的范围中排除才行。
代码清单4-13

// main.cpp
// 错误的代码
namespace ns_ks04_02 {
    int main(int argc, char* argv[])  {
    }
}

3)用了命名空间也不是一劳永逸
软件开发组织应制定软件研发管理制度并且严格执行。比如,制定命名空间管理规范,规定对外引出的类或接口必须提供命名空间保护、命名空间的名称需要提请相关机构审核等等。在规范的软件研发活动中,使用命名空间进行管理是最最基础的工作,因为这会避免很多不必要的问题。即使认为目前开发的类不会跟别人重名,也应该从一开始就养成使用命名空间的良好习惯。因为良好的习惯会潜移默化地影响软件研发活动,对软件研发人员的未来之路肯定会产生有益的影响。
----------------------------------------------------------------------------------------------------------------------------------------------
《Qt 5/PyQt 5实战指南》目录
分类:Qr入门与提高|回复:0|浏览:375|全站可见|转载
 

Powered by phpwind v8.7 Certificate Copyright Time now is:05-02 20:39
©2005-2016 QTCN开发网 版权所有 Gzip disabled