c++ 的namespace及注意事项

前文

下文中的出现的"当前域"为"当前作用域"的简写
namepsace在c++中是用来避免不同模块下相同名字冲突的一种关键字,本文粗略的介绍了一下namespace的使用以及需要注意的地方:
1.可通过显示指定namespace,or使用using引入符号的方式, or使用using namepsace加载整个namespace的方式使用一个名称空间下的符号
2.显示指定符号所属namespace的情况下,无论该表达式在哪里都是按照namespace绝对路径进行匹配而不是相对路径
3.using 指令是存在作用域,允许同时使用多个namespace,同时使用多个namespace存在相同的符号并不会覆盖,但编译会包ambigious
4.using namespace相当于在当前域把变量导入全局,会出现局部变量覆盖全局变量的情况;直接使用using引入变量,相当于在当前域定义变量,不允许定义同名变量,否则报错。

正文

使用namespace

下文简单的创建了一个名为n1的namespace,在其中放入了一个变量number,并在main()中使用了它

namespace n1{
    int number = 1;
};

int main(){
    //1.显式指出使用那个namespace下的number
    std::cout<<n1::number<<std::endl; 
    
    //2.引入n1::number后再使用它
    using n1::number;                
    std::cout<<number<<std::endl;
    return 0;
}

还有另一种方式获取到n1::number,可以通过using namespace加载整个namespace进来,但这种方式有其复杂性(后文详述),通常不推荐使用

namespace n1{
    int number = 1;
}

int main(){
    using namespace n1;        //使用namespace n1
    std::cout<<number<<std::endl; 

    return 0;
}

符号的namepsace查找规则

由于namespace是支持嵌套的,在显式指出符号所属的namespace的情况下,无论这个表达式放在什么地方,都是按照绝对路径从头开始匹配namespace,什么意思呢, 如下:

namespace n1{
    void fn(){
        std::cout<<"1"; //这里是去找std::cout, 而不是找 n1::std::cout
    }
}

global namspace

因为编译器为程序默认创建使用一个的global namespace(未显示指定在其余namespace下的定义生命变量都在global namespace下), 对于global namespace, 直接使用::, 前面什么都不需要加

int number = 0;

int main(){
    std::cout<<::temp<<std::endl;
return 0;
}

作用域

下面的例子显示了 using 是有作用域的,和一般的变量的作用域规则一样

namespace n1{
    int number = 1;
}

namespace n2{
    int number = 2;
}

int main(){
    {
        using  n1::number;
        std::cout<<number<<std::endl;     // 1 输出n1::number
        {
            using  n2::number;
            std::cout<<number<<std::endl; // 2 输出n2::number
        }
        std::cout<<number<<std::endl;     // 1 输出n1::number
    }
    return 0;
}

覆盖

当使用using namespace的时候,就会使用一个namespace,同时支持多个namespace的使用,在同时使用多个namespace的情况下,是会存在同名符号冲突的情况的,如下:
此时还是需要通过显示的指出所属namespace来解决

int number = 0;         //global namespace

namespace n1{
    int number = 1;      //n1 namespace
}

int main(){
    using namespace n1;
    std::cout<<number<<std::endl; //由于同时存在两个全局变量number,所以此处会报ambigious的错误
return 0;
}

但如果此处using的变量则没有问题,其相当于在当前域引入了一个变量number

int number = 0;

namespace n1{
    int number = 1;
}

int main(){
    using n1::number;              //声明接下来要使用n1::number了,接下里的number都是它,相当于在当前域引入了一个变量number
    std::cout<<number<<std::endl; //没问题,输出1
return 0;
}

当使用一个namespace的时候,就相当于在当前域把该namespace的变量都导入全局中了,如往常,局部变量会覆盖全局变量

namespace n1{
    int number = 1;
}

int main(){
    int number = 0;
    using namespace n1;
    std::cout<<number<<std::endl;//输出的结果为0, 局部变量覆盖了n1::number
return 0;
}

但是要注意,如果是引入变量到当前域,和之前所说的一样相当于定义一个变量,编译器严格控制了,不允许再定义相同的符号

namespace n1{
    int number = 1;
}

int main(){
    using n1::number;    // error: redeclaration of ‘int number’
    int number = 0;
return 0;
}

猜你喜欢

转载自www.cnblogs.com/ishen/p/12078652.html