掘根宝典之C++名称空间(using声明和using编译指令)

为什么要引入名称空间

C++引入了名称空间的概念,主要是为了解决命名冲突的问题。在大型项目中,经常会有多个开发人员同时开发,每个人都可能定义自己的函数、类、变量等。如果不使用名称空间,可能会出现相同名称的定义,导致编译错误或者运行时错误。

通过引入名称空间,可以将不同的代码块划分为不同的命名空间,从而避免冲突。每个名称空间内部的定义都是独立的,不会与其他名称空间冲突。这使得代码更具可读性、可维护性和可扩展性。

另外,名称空间还可以提供代码的逻辑组织和分层结构。通过命名空间可以将相关的函数、类、变量等组织在一起,便于代码的管理和理解。

总的来说,引入名称空间有助于解决命名冲突问题,提高代码的可读性和可维护性,以及组织代码的逻辑结构。

传统的c++名称空间

声明区域 

声明区域是可以在其中进行声明的区域。

例如在函数外声明全局变量,对于这种变量,其声明区域为其声明所在的文件。对于在函数中声明的变量,其声明区域为声明所在的代码块。

你可能发现了,这跟作用域的范围好像是一样的,但是实际上比作用域的范围稍大一点哦

潜在作用域

变量的潜在作用域从声明点开始到声明区域的结尾。因此潜在作用域比声明区域小,这是由于变量必须定义后才能使用。

然而,变量并非在其潜在作用域的任何位置都是可见的。例如,它可能被另一个在嵌套声明区域中声明的同名变量隐藏。例如在函数中声明的局部变量将隐藏在同一个文件中声明的全局变量

C++新名称空间特性 

c++通过定义一种新的声明区域来创建命名的名称空间,这样子做的目的是提供一个声明名称的区域。一个名称空间中的名称不会与另一个名称空间的相同名称发生冲突,同时允许程序的其他部分使用该名称空间中声明的东西。

C++中的命名空间(namespace)是一种用来组织代码的机制,它可以将相关的变量、函数、类等放在一个逻辑上的容器中,以便更好地组织和管理代码。

命名空间可以避免不同部分的代码之间发生命名冲突,特别是当多个库或代码模块中存在相同名称的变量、函数或类时。命名空间可以将这些具有相同名称的实体划分到不同的命名空间中,从而解决命名冲突的问题

在C++中,命名空间是通过关键字"namespace"来定义的,如下所示:

namespace mynamespace {
    // 命名空间中的代码
    int myVariable;
    void myFunction();
}

1.名称空间可以是全局的,也可以位于另外一个名称空间中,但不能位于代码块里。因此,在默认情况下,在名称空间中声明的名称的链接性为外部的(除非它引用了常量)

2.任何名称空间中的名称都不会和其他名称空间中的名称发生冲突。

举个例子

namespace A
{
int a=9;
}
namespace B
{
int a=8;
}
//完全没有问题

3.名称空间是开放的,可以把名称加入到已有的名称空间里,即可在里面定义变量,函数等

4.例如原来的jack名称空间为A()函数提供了原型。可以在文件后面(或者另外一个文件中)

再次使用jack()名称空间来提供该函数的代码。

5.可以通过"::"操作符来访问命名空间中的成员,如下所示:

mynamespace::myVariable = 123;
mynamespace::myFunction();

我们经常会看到下面这种代码

std::cin>>a;
std::cout<

 因为std也是一个名称空间,里面就包含了cout,cin,endl;

命名空间还可以嵌套使用,形成命名空间的层次结构,以进一步组织代码。

使用命名空间可以提高代码的可读性和可维护性,特别是在大型项目中。它可以将相关的代码组织在一起,并避免命名冲突的问题。

首先我们来了解一下未限定的名称,限定的名称;

未限定的名称:不包含名称空间的名称(比如cout)

限定的名称:包含名称空间的名称(比如std::cout)

我们不希望每次使用名称时都对它进行限定,所以我们引入了using声明和using编译指令来简化对名称空间中名称的使用

using声明

using声明由被限定的名称和它前面的关键字using组成

比如

using std::endl;
using std::cout;

using声明将特定的名称添加到它所属的声明区域中。完成该声明后使用该特定名称时可以直接使用未限定的名称,不用再使用限定的名称。

我们可以看个例子

#include
using std::cout;
using std::endl;
int main()
{
	cout << "加入成功" << endl;//可以使用未限定的名称
}

如果没有用using声明,(不用using编译指令的情况下),我们就得用限定的名称

#include
int main()
{
	std::cout << "加入成功" << std::endl;//使用限定的名称
}

使用using声明相当于引用了一个变量,我们可以把这条语句当作引用声明,就像引用别的文件的全局变量一样,using声明引入的变量/函数的特性和文件间用extern引用的全局变量的特性差不多我们可以看看几个例子

#include
using namespace std;
namespace A
{
	int a = 1;
}
int main()
{
	using A::a;
	{
		cout << a << endl;//结果是1
		int a = 2;
		cout << a << endl;//结果是2
	}
	cout << a<< endl;//结果是1
}

这我们就不作解释了,就作用域的问题,内部覆盖外部的问题,不懂的看我上一篇文章

#include
using namespace std;
namespace A
{
	int a = 1;
}
int main()
{
	using A::a;
int a=4;//这是不行的,因为using声明相当于引入了一个变量
//在同一声明区域内,不能再定义重名的变量
}

注意using声明的防重名的机制

#include
using namespace std;
namespace A
{
	int a = 1;
}
using A::a;
int main()
{	
    {
		cout << a << endl;//结果是1
		int a = 2;
		cout << a << endl;//结果是2
	}
	cout << a<< endl;//结果是1
}

这时a作为全局变量

还有一点要注意啊,不能声明多个名称空间里的相同名称

using A::a;
using B::a;//这是不行的
cout<

using编译指令

using声明使一个名称可用,而using编译指令使名称空间里所有名称都可用。

只对当前这个文件有用

using编译指令由using  namespace和名称空间名组成

比如我们最常见的

using namespace std;

1.在全局声明区域中使用using编译指令,将使该名称空间的名称全局可用

比如

#include
using namespace std;
...
int main()
{
...
}

2.在函数里面使用using编译指令,将使其中的名称在该函数可用

比如

#include
...
int main()
{
using namespace std;
...
}

使用using编译指令和使用多个using声明是不一样的。

使用using声明时,就好像声明了相应的名称一样,如果某个名称已经在函数中声明了,则不能再用using声明导入相同的名称。

然而,使用using编译指令时,将进行名称解析,就像在包含using声明和名称空间本身的最小声明区域中声明了名称一样。 

我们可以看个例子

#include
using namespace std;
namespace A
{
	int a = 1;
}
int main()
{
    using namespace A;
	cout << a << endl;//结果是1
	int a = 2;
	cout << a << endl;//结果是2
}

我们惊奇的发现,再定义一个重名的变量a,系统居然没有报错。这是using编译指令和using声明的区别

我们可以看看using声明

#include
using namespace std;
namespace A
{
	int a = 1;
}
int main()
{
	using A::a;
	cout << a << endl;
	int a = 2;//发现这不可以
	cout << a << endl;
}

编译器将禁止这么做

假设名称空间和声明区域定义了相同的名称。如果试图使用using声明将名称空间的名称导入该声明区域,则这两个名称会发生冲突,从而出错。如果使用using编译指令将该名称空间的名称导入该声明区域,则局部版本将隐藏名称空间版本

所以说,使用using声明比使用using编译指令安全很多。我们应该使用using声明而不是using编译指令。或者我们直接使用作用域解析运算符::,这也不错

#include
int main()
{
std::cout<<“hello world"<

名称空间的其他特性

可以将名称空间进行嵌套

namespace A
{
namespace B
{
int b;
}
int a;
}

要访问b,我们可以使用

using A::B::b;

可以在名称空间使用using声明和using编译指令

namespace A
{
using namespace B;
using C::c;
...
}

对这种情况,我们如何使用c呢?

A::c;
C::c;

 以上这两种情况都是可以的

 可以使用命名空间别名来简化访问命名空间中成员的代码

如下所示:

namespace ns = mynamespace;
ns::myVariable = 123;
ns::myFunction();

你可能感兴趣的:(c++,c++,开发语言)