问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C++命名空间(namespace)产生原因,特点,空间应用,好处

创作时间:
作者:
@小白创作中心

C++命名空间(namespace)产生原因,特点,空间应用,好处

引用
CSDN
1.
https://blog.csdn.net/LJY_CF/article/details/142601787

C++中的命名空间(namespace)是解决命名冲突和提高代码组织性的重要工具。本文将详细介绍命名空间的产生原因、特点以及使用方法,并通过代码示例帮助读者更好地理解其应用场景。

1. namespace产生原因

在C语言中,变量、函数,以至于类都是大量存在的,因此会产生大量的名称存在于全局作用域中,可能产生很多冲突。为避免命名冲突和名字的污染,C++引入了关键字namespace来解决这种问题。

1.2 查找规则

C/C++规定用任何变量类型的函数都要向上访问,在向上的过程中去找到他的出处。在编译时候查找没有在去全局中找。

例如,在C语言中rand是包含在头文件#include<stdlib.h>中的函数,因此编译器无法判断是函数还是变量。但事实上用C++可以完美解决。

2. namespace的特点

2.1 用namespace来定义命名空间

后加名字加{成员},可定义变量/函数/类型。

  1. 在命名空间中定义的变量。
  2. 定义函数。
  3. 定义结构体类型。

2.2 本质是定义一个全局域各自独立

如2.1中的a在不同的域中可以定义同名且不冲突。

2.3 C++中的域

函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找一个变量/函数/ 类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响 编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。

局部域

局部域是指在函数、代码块(如if、for、while语句块)内部定义的变量所处的作用域。在局部域中定义的变量,其生命周期从定义的位置开始,到所在的代码块结束时终止。当程序执行离开该代码块时,局部变量所占用的内存会被自动释放。

#include <iostream>
void testLocalScope() {
    // 局部变量 a,生命周期从这里开始
    int a = 10;
    std::cout << "Local variable a: " << a << std::endl;
    // 代码块结束,局部变量 a 的生命周期结束
}
int main() {
    testLocalScope();
    // 这里无法访问局部变量 a
    return 0;
}

全局域

全局域是指在所有函数、类和命名空间之外定义的变量所处的作用域。全局变量的生命周期从程序开始执行时就已经分配内存,直到程序结束时才会释放内存。

#include <iostream>
// 全局变量 b,生命周期从程序开始
int b = 20;
void testGlobalScope() {
    std::cout << "Global variable b: " << b << std::endl;
}
int main() {
    testGlobalScope();
    // 全局变量 b 仍然可以访问
    std::cout << "Global variable b in main: " << b << std::endl;
    // 程序结束,全局变量 b 的生命周期结束
    return 0;
}

命名空间域

命名空间域主要用于解决命名冲突的问题,它只是对标识符进行逻辑上的分组,并不影响变量的生命周期。在命名空间中定义的变量,其生命周期取决于它是全局变量还是局部变量。

#include <iostream>
// 全局命名空间
namespace GlobalNS {
    int globalVar = 10;
    void globalFunction() {
        std::cout << "This is a function in the global namespace. globalVar = " << globalVar << std::endl;
    }
}
void testLocalNamespace() {
    // 局部命名空间
    namespace LocalNS {
        int localVar = 20;
        void localFunction() {
            std::cout << "This is a function in the local namespace. localVar = " << localVar << std::endl;
        }
    }
    // 使用局部命名空间中的变量和函数
    std::cout << "Value of localVar in LocalNS: " << LocalNS::localVar << std::endl;
    LocalNS::localFunction();
    // 也可以使用全局命名空间中的变量和函数
    std::cout << "Value of globalVar in GlobalNS: " << GlobalNS::globalVar << std::endl;
    GlobalNS::globalFunction();
}
int main() {
    // 可以直接在 main 函数中使用全局命名空间
    std::cout << "Value of globalVar in GlobalNS (from main): " << GlobalNS::globalVar << std::endl;
    GlobalNS::globalFunction();
    // 调用包含局部命名空间的函数
    testLocalNamespace();
    // 尝试在 main 函数中使用局部命名空间(这是错误的,因为局部命名空间超出了作用域)
    // 下面这行代码会导致编译错误
    // std::cout << LocalNS::localVar << std::endl;
    return 0;
}

域的名字在自己内部只能用一次,同一个域名字不能重复,但不同的域可以

2.4 namespace只能定义在全局,当然他还可以嵌套定义

图1;嵌套后要区别调用

图二注:当库很大或项目大还可以套中套来解决命名冲突

2.5 项目工程中多文件

项目工程中多文件中定义的同名namespace会认为是一个namespace,不会冲突。多文件中可以定义同名namespace,他们会默认合并到一起,就像同一个namespace一样

定个文件一个命名空间都会封在一起

例如:当同时定义栈与队列 会产生多个文件

3. 命名空间使用

编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以 下面程序会编译报错。所以我们要使用命名空间中定义的变量/函数,有三种方式:

3.1 指定命名空间访问

不易出错,推荐使用

3.2 展开命名空间中全部成员(展开头文件与命名空间的区别)

展开命名空间中全部成员--》变成全局变量因此可能造成命名冲突

展开头文件是将头文件在预处理阶段将头文件的代码拷贝过来

不推荐,冲突风险大,但是在小练习中为方便推荐使用。

3.3 折中using将命名空间中某个成员展开

当a用的不多但是b用的多是将b解开变成全局;

项目中经常访问的不存在冲突的成员推荐这种方式

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号