c++|c++ namespace

学习c++的同学大概非常习惯在程序的开头部分加上这句:

using namespace std;

可能由于太熟悉了,反而忽略了这句到底是做什么的。这句中,一共有3个关键字,抛开第三个关键字std,我们只关注于前面的2个:using和namespace。
先说using,using一般来说有2个功能:
1 将std命名空间的内容引入本命名空间,这句话很抽象,但是简单说,就是可以让你少打几个字。原来需要std::string这样才能访问的地方,可以简化为string就可以了。当你的命名空间很长很复杂时,using显的很有用,比如:
namespace abcd { namespace efgh { namespace ijk { class A; } } }

如果你想访问A,那么完整的写法是:abcd::efgh::ijk::A。
当然了,不得不承认,using的存在是和namespace的封装思想相违背的,所以在通常的编程规范里,严禁在头文件中using命名空间。
2 使用父类被隐藏的函数。比如:
class A { public: int fun(int); void fun(); }; class B : public A { public: using A::fun; int fun(double); }; B b; b.fun(); //without using, error

【c++|c++ namespace】这里面涉及c++继承的隐藏,不展开。
其实using的作用非常有限,而且通常情况下属于那种可有可无的.....
而另一个关键字namespace,就相对来说重要的多,namespace的存在,使得一些大型的项目开发变得相对容易,各个模块可以非常完美的区分开来,再也不用担心和其他人的函数或者类重名。
namespace的实现原理非常简单,在编译时,同一个命名空间的函数或者变量将在名字前增加命名空间名,比如上文中我们的class A,在编译后可能变成: abcd_efgh_ijk_A。
在自己的命名空间内有个函数,它正好和全局范围内的某个函数重名,比如:
int fun(); //global namespace A { int fun() { ::fun(); //call golbal fun } }

前面的这些基本上都是铺垫......
接下来才是重点....
我们在编写一个类的时候,经常会在这个类中用到其他类的一些信息,比如:
// a.h namespace lbs { class A { int a; ... }; }

// b.h namespace lbs { class B { A a; ... } }

在上文中,如果想在类B中组合类A,那么需要在b.h中#include "a.h",因为编译器需要A的定义,而需要A定义的目的是为了确定A的大小以便在编译时分配空间。
如果在b.h中#include "a.h",那么程序的耦合度会很高,因为你将在a.h中将许多不必要的信息都添加进来,尤其是当B这个类很大时,你需要在b.h中#include非常多的类,程序将显得异常笨重,而且逻辑很混乱。
有没有解决方案呢?
顺着我们刚才的思路,编译器需要的是A的大小,那么只需要将A a,变为A* a或者A& a,就可以了。在b.h中,不再#include "a.h",而是使用一个类的声明替代,如下:
// b.h namespace lbs { class A; //declare class B { A* a; ... }; }

这样之后,可以使得b.h轻便许多,程序整体的耦合度很低,可是当你需要使用一个其他命名空间的类,该如何做呢?比如下面这样:
// a.h namespace lbs { namespace common { class A { int a; ... }; } }

// b.h namespace lbs { namespace db_mm { class common::A; //error, common unknown class B { A* a; ... }; } }

这种涉及不同命名空间的声明,如果按照上面的方式写,将会编译错误,提示common命名空间unknown,因为系统不知道common是一个命名空间。所以呢,需要这样写:
// b.h namespace lbs { namespace common { class A; //declare }namespace db_mm { class B //definition { common::A* a; ... }; } }

当然了,在cpp文件中,还是需要#include所需要的所有头文件。

    推荐阅读