【C++】命名空间

在C语言中有下面一段代码:

#include <stdio.h>
int main() {
    int scanf = 0;
    scanf("%d", &scanf);
    return 0;
}

这段代码会报错。

首先 scanf 是一个函数名,不是C语言的关键字,所以定义一个名为 scanf 的局部变量是没有任何问题的。

但是,当我想调用 scanf 函数去给定义的临时变量 scanf 赋值的时候却出现了问题。

我们以为是函数名的 scanf 也被编译器当成了临时变量:

image-20220804201910112

亦或者是下面一段代码:

#include <stdio.h>
int scanf = 0;
int main() {
    printf("%d", scanf);
    return 0;
}

这段代码报错说 scanf 重定义。这段代码与上面不同的是 scanf 定义成了全局变量,而在头文件 stdio.hscanf 也被定义了一次。在预处理阶段会进行头文件的展开,这样就导致了报错所说的那个问题。

image-20220804202153004

上面两个案例就引出了一个问题——命名污染

C++ 为了解决这个问题,引入了命名空间


命名空间的定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

比如下面的一些使用方法:

//1. 普通的命名空间
namespace N1 // N1为命名空间的名称
{
	// 命名空间中的内容,既可以定义变量,也可以定义函数
    int a;
    int Add(int left, int right)
    {
    	return left + right;
    }
}

//2. 命名空间可以嵌套
namespace N2 {
    int a;
    int b;
    int Add(int left, int right) {
    	return left + right;
    }
    namespace N3 {
        int c;
        int d;
        int Sub(int left, int right){
            return left - right;
        }
    }
}

//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
namespace N1 {
    int Mul(int left, int right) {
        return left * right;
    }
}

解释一下第三段代码。

它和第一段代码的命名空间都叫 N1 ,命名空间相同的命名符号会在链接过程中合并,所以 aAddMul 是同属一个命名空间的。

一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中,当出了这个命名空间的作用域,里面定义的各种变量名也就跳出了生命周期。


命名空间的使用

我们在初次接触C++的代码时可能会看到下面的代码:

//1
using namespace std;
int main() {
    cout << "hello world" << endl;
    return 0;
}

//2
int main() {
    std::cout << "hello world" << std::endl;
    return 0;
}

//3
using std::cout;
int main() {
    cout << "hello world" << endl;
    return 0;
}

其实上面三段代码就反映了命名空间的三种主要使用方法。

下面解释一下。

首先说明一点,cout 是*C++*的输出函数,它是定义在命名空间 std 中的,std 中还定义了一个输入函数 cin ,下面讲解会拿它来举例。

1 处是将命名空间 std 全部展开,这也就意味着 std 中的任何一个变量名都不能被再次重定义,假如我添加一行 int cin = 0;编译器就会报错。这样的好处是对命名空间中的变量名可以直接使用,而不用加限定符。但缺点也同样明显,就是在协同工作中可能会引发命名冲突的问题

2 处是使用了命名空间名称+作用域限定符的方式。这样的好处是避免了命名冲突的问题,即使我又定义了一个 int cout = 0; 编译器也不会报错。缺点同样明显,就是使用起来太麻烦了。

3 处是工程中最标准也是最推荐的使用方式,对命名空间中的哪个成员用的多就单独把它引用进来,这样只需要避免重定义引进来的这个成员就可以规避命名冲突,这样最大程度地避免了命名冲突的问题,写起来代码也不会太麻烦。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LeePlace

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值