C++ namespace

一、什么是 namespace

1.1 C语言标识符作用域的缺陷

 在C语言中因为项目需要会定义各种全局变量、函数等,我们也会调用C语言标准库提供给我们的各种函数,这将会导致我们变量名、函数名与标准库中的发生命名冲突。

#include <stdio.h>
#include <stdlib.h>

int rand = 10; // 错误,与库函数rand命名冲突

int main()
{
	printf("%d\n", rand);  
}

在这里插入图片描述

1.2 namespace作用

 在C++中通过namespace来防止命名冲突,namespace相当一件隐身衣,在namespace中的变量、函数、类在namespace外面是看不到,访问不到的,相当于不存在,所以也就不会发生命名冲突。即一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中

二、namespace的定义

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

namespace kxl // kxl 为空间名字
{
	int rand = 10;
	
	int sum(int x,int y)
	{
		return x+y;
	}
	
	struct Person
	{
		char name[10];
		int age;
	};
}

2.1 命名空间可以嵌套定义

namespace kxl // kxl 为空间名字
{
	int rand = 10;
	
	namespace kdl
	{
		int x = 0;
		int rand = 20;
	}
}

小技巧

命名空间嵌套层次太多时,使用里面的成员会很麻烦,可以对嵌套的命名空间取别名,这样使用起来会更加方便

#include <iostream>

namespace kxl // kxl 为空间名字
{
	int rand = 10;
	
	namespace kdl
	{
		int x = 0;
		int rand = 20;
		
		namespace kzl
		{
			int rand = 30;
			int y = 5;
		}
	}
}

namespace alias_kzl = kxl::kdl::kzl; // 别名

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

2.2 可定义重复的命名空间

在一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间,但相同命名空间中的变量、函数、类不能重复定义

namespace kxl // kxl 为空间名字
{
	int rand = 10;
}

namespace kxl // kxl 为空间名字
{
	// int rand = 20;  错误,相同命名空间变量名相同,编译器不知道合并哪一个rand
	int x = 20;
}

最终编译器合并为


namespace kxl // kxl 为空间名字
{
	int rand = 10;
	int x = 20;
}

三、namespace使用

3.1 命名空间名称+作用域限定符使用

语法: 空间名称::标识符名
相当于告诉编译器去哪一个命名空间中找哪一个对象

namespace kxl // kxl 为空间名字
{
	int rand = 10;
	int x = 0;
	int y = 1;
	
	namespace kdl
	{
		int x = 20; 
		int z = 100;
	} 
}

int main()
{
	printf("%d\n", kxl::rand); // kxl 为命名空间名称,:: 为作用域限定符, rand 为变量名
	printf("%d\n", kxl::kdl::x); // 访问kxl命名空间中的kdl里面的x变量
	return 0;
}

3.2 using将命名空间中成员引入

如果空间中某个对象经常使用,用3.1的方法比较繁琐,可以使用using关键字将空间中某个对象引入,即这个对象不隐身了,作用域为全局作用域
语法: using 空间名称::标识符名;

namespace kxl // kxl 为空间名字
{
	int rand = 10;
	int x = 0;
	int y = 1;
}

using kxl::x;
// using kxl::rand;  不要将rand这样引入,否则rand和库函数rand发生命名冲突
int main()
{
	printf("%d\n",x);
	return 0;
}

3.3 使用using namespace将整个空间成员引入

使用using namespace将整个空间成员引入,即隐身衣失效了,空间中所有对象的作用域都是全局作用域,可以直接访问,但是与C++中引入命名空间初衷相矛盾,一般不建议这样用

语法:using namespce 空间名称;

namespace kxl // kxl 为空间名字
{
	int x = 0;
	int y = 1;
}

using namespace kxl;

int main()
{
	printf("%d\n", x); // x 相当于正常定义的全局变量,可以直接访问
	printf("%d\n", y);
	return 0;
}

四、C++ 11 ~ C++ 20

4.1 C++ 11 内联命名空间

内联命名空间(Inline Namespace)是 C++11 中的一个特性,它允许在命名空间中嵌套另一个命名空间,并且将其内容直接导出到外部命名空间中,即内联命名空间的成员会被视为父命名空间的成员。

语法: inline 空间名

/*
可以将内联命名空间用作版本控制机制,以管理对库的公共接口的更改。 例如,可以创建单个父命名空间,并将接口的每个版本封装到嵌套在父命名空间内的其自己的命名空间中。 保留最新或首选的版本的命名空间限定为内联,并因此以父命名空间的直接成员的形式公开。
*/
namespace Test
{
    namespace v1
    {
        void Func()
        {
            std::cout << "v1 version" << std::endl;
        }
    }

    inline namespace v2 // v2 
    {
        void Func()
        {
            std::cout << "v2 version" << std::endl;
        }
    }
}


Test::v1::Func(); // 输出: v1 version 
Test::Func(); // 输出: v2 version 

4.2 C++ 17 嵌套命名空间简洁写法

C++17 允许使用简洁写法描述嵌套的命名空间,可以更清晰地表示出命名空间之间的逻辑关系。

namespace A::B::C // C++ 17
{
    void Fun()
    {
        std::cout << "Test()" << std::endl;
    }
}

上面代码等同于:
namespace A
{
    namespace B
    {
        namespace C
        {
            void Fun()
            {
                std::cout << "Test()" << std::endl;
            }
        }
    }
}

4.3 C++ 20

C++ 20支持简洁定义内联命名空间

namespace A::inline B::C // C++ 20支持,C++ 17不支持
{
    void Fun()
    {
        std::cout << "Test()" << std::endl;
    }
}

上面代码等同于:
namespace A
{
    inline namespace B
    {
        namespace C
        {
            void Fun()
            {
                std::cout << "Test()" << std::endl;
            }
        }
    }
}
  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
回答: 在C++中,命名空间(namespace)是一种用来避免名称冲突的机制。当工程越大,使用多个厂商的类库时,名称冲突的可能性就越大。为了避免这种冲突,C++引入了命名空间的概念。命名空间可以将一组相关的标识符包装在一个作用域内,从而限制其在程序中的可见性。通过使用命名空间,可以更好地控制标识符的作用域,避免名称冲突。\[2\] 在C++中,可以使用命名空间嵌套来组织代码。当命名空间嵌套层次太多时,使用其中的成员会变得很麻烦。为了方便使用,可以对嵌套的命名空间取别名。通过使用别名,可以简化代码中对命名空间成员的访问。例如,在代码中可以使用"namespace alias_kzl = kxl::kdl::kzl;"来为"kxl::kdl::kzl"命名空间取别名为"alias_kzl"。然后可以通过"alias_kzl::y"来访问"kxl::kdl::kzl"命名空间中的"y"成员。\[1\] 在使用命名空间时,有多种方式可以引入命名空间中的成员。一种常见的方式是使用"using"关键字,例如"using namespace std;"可以将"std"命名空间中的成员引入当前作用域。然而,这种方式可能会导致名称冲突和不明确的代码。因此,一种更好的做法是使用限定符来访问命名空间中的成员,例如"std::cout"。这样可以明确指定使用的是哪个命名空间中的成员,避免冲突和歧义。\[3\] #### 引用[.reference_title] - *1* [C++ namespace](https://blog.csdn.net/kjl167/article/details/126244107)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C++ namespace用法详细介绍](https://blog.csdn.net/Yifancoder/article/details/124127828)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [C++ namespace详解](https://blog.csdn.net/weixin_30808575/article/details/96584787)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值