欢迎来到博主的专栏——c++编程
博主ID:代码小豪
命名空间
c++是为了解决C语言的语言缺陷而发展出来的语言。为此、c++衍生出了许多C语言没有的关键字和特性。namespace(命名空间)就是c++新增的关键字
命名空间是为了解决C语言的缺陷而设计的关键字,那么C语言待解决的缺陷是什么呢?
大型项目的代码动辄十几万行,且由多人共同编写。那么在这么多人定义的函数名和标识符中,出现命名冲突是非常常见的事,可能今天你刚编写的库没有问题,明天同事一引用你的库就发生的报错。于是就需要在众多的库当中找到命名冲突,这对效率来说还是有所影响的。
C语言设置了两个域——全局域和局部域。定义在不同域的变量不会冲突,且遵守局部优先这个规则。
比如:
int exit = 10;
int main()
{
int exit = 0;
printf("%d",exit)
);
return 0;
}
在全局域中有一个全局变量exit。局部域中有一个局部变量exit。根据局部优先的规则,printf函数中的参数为局部变量。
域限定符
如果想要在局部域当中调用全局变量exit。c++推出了一个新的操作符,域限定符(::),使用域限定符可以指定变量存在的域。
当域限定符的前面没有标识符时,默认查找全局域。
如:
int exit = 10;
int main()
{
int exit = 0;
printf("%d",::exit);//限定exit查找的域为全局域
return 0;
}
命名空间域
在上述的代码中加入库函数<stdlib.h>。由于预处理的特性,<stdlib.h>中的库函数会在全局域中展开(可以理解为库函数全定义在了全局域中)。而stdlib中定义的exit函数与全局域中的exit变量重名,产生了命名冲突。
#include<stdlib.h>
int exit = 10;//全局域中的变量与库函数exit发生冲突
int main()
{
int exit = 0;
printf("%d",exit);
return 0;
}
C语言中只有全局域和局部域的特性很容易导致命名冲突,因此c++增加了一个新域——命名空间域,在命名空间域中的标识符可以和全局域,局部域的标识符相同而不冲突。
命名空间域可以由用户(程序员)创建,使用方式为
namespace name
{
statement;
}
name是用户为该命名空间域设置的域名。在这个域当中可以包含函数声明、变量、结构体、函数定义等等。这个域不会与其他域冲突。。
namespace MySpace
{
struct data//结构体声明
{
int x;
int y;
};
int exit = 10;//变量
int Init(int x, int y);//函数声明
int add(int x ,int y)//函数定义
{
return x + y;
}
}
想要在其他域中使用命名空间域中的数据,就需要用到域限定符(::)。
int main()
{
int exit = 0;
printf("%p\n",::exit);//全局域中的exit
printf("%d\n",MySpace::exit);//MySpace域中的exit
printf("%d\n",exit);//局部域中的exit
MySpace::add(10,20);//调用MySpace域中的add
return 0;
}
命名空间域的数据是隐藏起来的,如何理解这个隐藏的意思呢?
比如现在访问一个exit变量,这个变量的默认访问顺序如下:
(1)访问局部域(局部优先)
(2)访问全局域
如果exit变量只存在于命名空间中,不会被默认查找,只能通过域限定符来指定。
namespace MySpace
{
int exit = 10;//定义在局部空间域
}
int main()
{
printf("%d", exit);//error 未定义标识符
printf("%d", MySpace::exit);//正确访问
}
展开命名空间
前面提到了命名空间是隐藏起来的,想要命名空间不再隐藏,可以将命名空间展开。
using namespace MySpace;
展开命名空间后,编译器的默认查找顺序为:
(1)局部域
(2)全局域
(3)展开的命名空间域。
c++头文件中的函数都由一个命名空间std(标准库)封装起来,如果想要调用库函数,可以展开命名空间std
using namespace std;
注意是引用c++头文件,比如<iostream>。引用c语言中的头文件不需要展开标准库。
展开后的命名空间会和全局域的标识符发生命名冲突。因此最好的方法是展开特定标识符
比如使用cout。
using std::cout;
这样就是只展开cout函数,其他函数依然封装在标准库中。
缺省函数
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实
参则采用该形参的缺省值,否则使用指定的实参。
void func(int n = 10)//这里10为缺省值
{
std::cout << n << std::endl;//打印n的值
}
int main()
{
func();//没有实参,参数为缺省值10
func(20);//有实参,参数为实参20
}