【C++】简单学——命名空间

目录

命名空间的由来

命名空间

概念

语法

为什么可以避免命名冲突?

使用方法

命名空间的用法一:指定命名空间

命名空间的用法二:全展开命名空间

命名空间的用法三:部分展开命名空间

命名空间的用法四:命名空间里面嵌套命名空间

使用建议

实际的应用场景


命名空间的由来

C语言中存在着某些问题:全局变量可能会面临命名冲突的问题

#include <stdio.h>

int rand = 10;

int main()
{
	printf("%d", rand);
	
	return 0;
}

以上代码是正常运行的(打印10)

但如果再包一个头文件<stdlib.h>

就会报错(包头文件的原理是将头文件里面的东西直接拷贝过来)

因为在<stdlib.h>中,存在着一个与rand同名的变量,名字之间产生了冲突

这些问题有可能会出现在:

程序员写的变量名和库里的变量名冲突

在公司里面,两个程序员都写了某一个重名的变量

C语言未能解决该问题(只能相互改名)

而c++解决这个问题的方式就是添加命名空间(不同的域里面可以定义同名的变量)

命名空间

概念

命名空间(Namespace)是 C++ 中用来避免命名冲突的一种机制;

通过命名空间,你可以创建一个独立的作用域,在命名空间中可以定义变量、函数、类等(因为这三个东西命名方面都可能会冲突)

这些定义在命名空间内部的标识符在命名空间外部是不可见的,从而避免了与其他部分代码的命名冲突。

简要说明,即:

全局域:野生的菜地

局部域:自家的菜地

命名空间:张大爷的菜地

如果没有张大爷的允许,就不允许去张大爷家的菜地里摘菜(访问)

目前我们学习的域:全局域,局部域←影响生命周期和访问,命名空间域←只会影响访问

语法

namespace ns1 (命名空间的名字)
{

	int rand = 10;(变量)

	struct Node(结构体)
	{
		char* name;
		int age;
	};

	int Add(int a, int b) (函数)
	{
		return a + b;
	}
}

为什么可以避免命名冲突?

表层角度:

将两个同名的变量分别用两个不同的命名空间圈起来(此时的x还是全局变量,只不过是放到了命名空间域里面,做了名字的隔离)

所以,命名空间解决了名字隔离、命名冲突的问题

底层角度:

编译器使用一个变量时,会进行搜索,

编译器的搜索原则:

未指定域:

  1. 首先搜索局部域,
  2. 再搜索全局域,找完了还是没找到的话就会报错

指定了域:

  1. 如果指定了域,就直接到指定的域里搜索指定变量

所以,命名空间解决了变量的搜索问题

问:如果两个命名空间冲突了呢?

答:命名空间之间可以同名

当两个命名空间重名时,两个就会合并在一起

所以,如果两个重名的命名空间里面写了同名的变量,会因为合并到了同一个命名空间而产生重定义的报错

使用方法

命名空间的用法一:指定命名空间

域作用限定符( ::)

用法:

namespace ns1 (命名空间的名字)
{

	int rand = 10;(变量)

	struct Node(结构体)
	{
		char* name;
		int age;
	};

	int Add(int a, int b) (函数)
	{    
		return a + b;
	}
}

///以上内容均相同

int main()
{

    printf("%d", ns1::rand);(打印10)

    
    ns1::Add(1 , 2);


    struct ns1::Node x;(要注意ns1:: 不是放在开头的)
    

    return 0;
}

(如果说我们想要去访问全局的变量而不是局部的变量,可以通过域作用限定符来指定)

int rand = 10;

int main()
{
    int rand = 3;

    printf("%d", ::rand);
    //↑↑↑
    //打印10
    return 0;
}

命名空间的用法二:全展开命名空间

语法:

namespace ns1 (命名空间的名字)
{

	int rand = 10;(变量)

	struct Node(结构体)
	{
		char* name;
		int age;
	};

	int Add(int a, int b) (函数)
	{    
		return a + b;
	}
}

///以上部分均相同


using namespace ns1;(以下的内容不用再指定命名空间)

int main()
{

    printf("%d", rand);(打印10)

    
    Add(1 , 2);


    struct Node x;
    

    return 0;
}

张大爷把自家的菜地公开了,所有人都可以去张大爷家摘菜了

(展开相当于让命名空间内的东西变成全局的)

原理:放开了访问权限

与头文件的展开不同

头文件展开:将头文件直接拷贝到当前文件下

命名空间展开:将访问权限公开

使用场景:平时自己写练习代码,为了方便可以全展开

优势:大量访问时比较方便

劣势:全展开相当于直接变成全局的,会产生命名冲突的问题,慎用!

命名空间的用法三:部分展开命名空间

语法:

namespace ns1 (命名空间的名字)
{

	int rand = 10;(变量)

	struct Node(结构体)
	{
		char* name;
		int age;
	};

	int Add(int a, int b) (函数)
	{    
		return a + b;
	}
}

///以上部分均相同


using ns1::rand;(以下的内容只有rand不用指定命名空间)

int main()
{

    printf("%d", rand);(打印10)

    
    ns1::Add(1 , 2);


    struct ns1::Node x;
    

    return 0;
}

使用场景:

如果某个头文件的函数或者变量等需要反复使用

但是每次使用都指定命名空间会很麻烦

又不敢去展开全部

就可以把常用的展开

命名空间的用法四:命名空间里面嵌套命名空间

语法:

namespace ns1 (命名空间的名字)
{

	int rand = 10;(变量)
    
    namespace ns2
    {
        int rand = 10000;(变量)
    }
}

///以上部分均相同



int main()
{

    printf("%d", ns1::rand);(打印10)

    printf("%d", ns1::ns2::rand);(打印10000)

    return 0;
}

使用场景:若公司项目要求将某些函数以及部分内容包含在同一个命名空间中,就可以在命名空间里面再套一个命名空间(怎么嵌套就怎么访问

使用建议

命名空间要么不展开,要么只展开部分常用的

实际的应用场景

 在c++中,实际的应用 场景:

在正常的项目中,可能会写出很多的.cpp文件(有可能是单独自己的,也有可能包了其他人的)

例如说写了一个链表和一个队列

----------------deque.h---------------
struct Node
{
	int val;
	struct Node* next;
	struct Node* prev;
};

struct deque
{
	struct Node* head;
	int length;
};

void Init(struct deque* head)
{};
void Push(int val, struct deque* head)
{};

-------------deque.h-------------------

↑↓如果将这两个头文件同时包在一起,由于他们的函数名Init和Push重名了,以及他们的Node结构体也重名了,结果就会报错

-------------Queue.h-------------------
struct Node
{
	int val;
	struct Node* next;
};

struct Queue
{
	struct Node* head;
	struct Node* tail;
	int size;
};

void Init(struct Queue* pq)
{};
void Push(struct Queue* pq, int x)
{};
-------------Queue.h-------------------

解决方法:

将两个结构体用不同的命名空间来包含起来

----------------deque.h---------------

struct Node
{
	int val;
	struct Node* next;
	struct Node* prev;
};

struct deque
{
	struct Node* head;
	int length;
};

void Init(struct deque* head)
{};
void Push(int val, struct deque* head)
{};

-------------deque.h-------------------

要使用上面的结构或者函数,只需要加上预作用限定符指定访问即可

  • 31
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CtrlZ大牛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值