c++ namespace

作者: littlersmall | 来源:发表于2016-01-12 13:02 被阅读339次

学习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++继承的隐藏,不展开。

其实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所需要的所有头文件。

相关文章

  • [C++之旅] 1 namespace

    [C++之旅] 1 namespace

  • C++入门基础

    C++入门基础 namespace专题讲座 namespace概念 所谓namespace,是指标识符的各种可见范...

  • C++ namespace

    A::x 类似于 A.x ,运行结果:

  • c++ namespace

    学习c++的同学大概非常习惯在程序的开头部分加上这句: 可能由于太熟悉了,反而忽略了这句到底是做什么的。这句中,一...

  • C++ 基础知识点大纲

    C++ C++对C的加强 namespace命名空间 C++命名空间基本概念 C++命名空间定义,使用语法,意义 ...

  • 1、C++基础:命名空间

    对using namespace std;的解释所谓namespace,是指标识符的各种可见范围。C++标准程序库...

  • 05 NDK-C++基础(一)

    1 C++对C的加强 1.1 namespace命名空间 1.1.1 C++命名空间基本概念 在C/C++中,变量...

  • C++之namespace

    为什么要有命名空间的出现 在C++中,名称(name)可以是符号常量、变量、宏、函数、结构、枚举、类和对象等等。为...

  • c++基础(namespace)

    有关namespace也称命名空间,想必大家并不默认,通过添加命令空间来解决同一结构函数的冲突的问题,我们 编译源...

  • ArcGis Qt跨平台开发【3】--地图开发起手式

    ArcGis Qt的C++开发包定义了namespace Esri::ArcGISRuntime,几乎所有...

网友评论

  • 金戈大王:原来还有这个问题,第一次听说,多谢了~
  • 曾樑:这东西在大学里搞死我了。。

本文标题:c++ namespace

本文链接:https://www.haomeiwen.com/subject/pjqckttx.html