1、双冒号
1.1 作为作用域解析运算符
#include <iostream>
class my_class{
public:
static void say(){
std::cout << "hello my_class" << std::endl;
}
};
namespace my_space{
void say(){
std::cout << "hello my_space" << std::endl;
}
}
int main() {
my_class::say();
my_space::say();
return 0;
}
如上方代码16行和17行所示,分别调用my_class 类内和my_space 名称空间内的say() 函数。
1.2 表示默认全局命名空间内的函数或变量
#include <iostream>
char test_char = 'a';
void say(){
std::cout << "hello global" << std::endl;
}
namespace my_space{
char test_char = 'b';
void say(){
std::cout << "全局的test_char为:" << ::test_char << std::endl;
std::cout << "my_space的test_char为:" << test_char << std::endl;
}
class my_class{
public:
static void say(){
std::cout << "hello my_class" << std::endl;
::say();
}
};
}
int main() {
my_space::my_class::say();
my_space::say();
say();
::say();
return 0;
}
::say() 意味着要去全局命名空间内寻找say() 函数。 而my_class 类中的静态成员才能以双冒号解析的方式引用。
2、命名空间namespace
一个大型的程序通常由不同模块构成,不同模块甚至可能是由不同人员开发的。不同模块中的类和函数之间可能会发生重名,这样就会引发错误。这就好像上海和武汉都有南京路,如果在缺乏上下文的情况下直接说出“南京路”就会产生歧义。但如果说“上海的南京路”或者“武汉的南京路”,歧义就会消除。命名空间起到的就是这样的作用。
2.1 全局命名空间
全局命名空间是默认的命名空间,所有声明的命名空间之外声明的标识符都在全局命名空间中。 main() 函数必须在全局明明空间中,也就是说,与main() 并列的标识符都是全局命名空间中的标识符。
2.2 匿名命名空间
匿名命名空间是一个需要显式声明但是没有名字的命名空间,声明方式如下
namespace{
匿名命名空间内的各种声明
}
匿名命名空间常被用来屏蔽不希望暴露给其他源文件的标识符。因为每个源文件的匿名命名空间是彼此把不同的,在一个源文件中没有办法访问其他源文件的匿名命名空间。
2.3 using 指令
using 指令有两种用法,一种是例如using namespace std 的using编译指令,还有一种是例如using std::cin 的using声明指令。
2.3.1 using声明指令
使用using声明指令后,被声明的标识符可以不用加域解析运算符直接引用。
#include "iostream"
using std::cin;
int main(){
char ch;
cin >> ch;
std::cout << ch <<std::endl;
return 0;
}
2.3.2 using编译指令
using编译指令相当于将其所在作用域中所有的标识符,自动加上域解析符
#include "iostream"
using namespace std;
int main(){
char ch;
cin >> ch;
cout << ch <<endl;
return 0;
}
如上述代码所示,一旦找到某未在当前作用域内声明的标识符,编译器就会再去using namespace 后声明的命名空间内寻找该标识符,一旦找到,就会自动在该标识符前面加上域解析符。于是上述代码就变成了
#include "iostream"
int main(){
char ch;
std::cin >> ch;
std::cout << ch <<std::endl;
return 0;
}
3、进阶
#include "iostream"
using namespace std;
namespace Jill{
double bucket(double n);
void fetch(){
cout << "hello Jill" << ::endl;
}
struct hill{ int name; };
}
int main(){
Jill::hill a;
Jill::fetch();
::cout << "hello world"<<endl;
return 0;
}
需要注意的是第8行::endl 和第17 行::cout 表示去全局命名空间中寻找endl 和cout ,然而全局名称空间中没有定义这两个标识符,所以编译器就去std中寻找他们,找到后就自动在前面加上了域解析符。
|