命名空间是表达多个变量和多个函数组合成一个组的方法。主要是为了解决名字(类型、变量、函数名)冲突的问题。
# 定义命名空间
用一个例子来说明:在 MyStudent.h
和 YourStudent.h
中都定义了 Student 类,并在 main 函数中包含这两个文件。
//MyStudent.cpp
class Student
{
public:
void Show() {cout << "MyStudent"; };
};
//YourStudent.cpp
class Student
{
public:
void Show() {cout << "YourStudent"; };
};
//main.cpp
#include"MyStudent.cpp"
#include"YourStudent.cpp"
int main()
{
Student s;
s.Show();
return 0;
}
以上代码会报错:Student 不明确
。
所以用 namespace
将两个代码分开:
//MyStudent.cpp
namespace MyStudent
{
class Student
{
public:
void Show() {cout << "MyStudent"; };
};
}
//YourStudent.cpp
namespace MyStudent
{
class Student
{
public:
void Show() {cout << "YourStudent"; };
};
}
//main.cpp
#include"MyStudent.cpp"
#include"YourStudent.cpp"
int main()
{
Student s;
s.Show();
return 0;
}
应该可以了。(注意 namespace
没有分号)
然而还是不行。因为没有指明用的是哪一个 namespace 的。
修改上一段的 main.cpp
:
//main.cpp
#include"MyStudent.cpp"
#include"YourStudent.cpp"
int main()
{
MyStudent::Student ms;
YourStudent::Student ys;
ms.Show();
ys.Show();
return 0;
}
总算能正常使用了。
注意这个 ::
符号,和类的也是一样,都是表明域运算符。
关于定义命名空间,再多说几句,namespace:
可以在全局范围定义
可以在另一个 namespace 中定义(形成嵌套 namespace)
不可以在函数、类的内部定义
定义可以不连续、分段定义(和类一样)
甚至可以没有名字,但是就不能跨文件调用,起到了类似
static
的效果
# using 语句
还可以使用 using namespace
语句,使得 using
作用域里的代码使用该 namespace 时可以省略 namespace 的名称。
(这里的 作用域
遵循正常的范围规则:从使用 using
开始,直到范围结束)
继续修改上一例的 main.cpp
:
//main.cpp
#include"MyStudent.cpp"
#include"YourStudent.cpp"
using namespace MyStudent;
int main()
{
Student ms;
YourStudent::Student ys;
ms.Show();
ys.Show();
return 0;
}
注意,如果在本例中对 MyStudent
和 YourStudent
都进行 using
,会报最开始就提到的 不明确
的错。
也可以使用名称空间的部分内容:
using std::cout;
# namespace std
C++ 标准语法库的所有代码都被包含在了 std 名称空间中。
这意味着,如果不指明名称空间,形如 string
sort
cout
的东西都无法使用。
所以,我们一般会在代码最开始,或 main 函数开头加一个 using namespace std
,或者将所有需要的代码加上 std::
。
另外,值得一提的是,如果在类中定义了和 C++ std 的同名成员函数,其他成员函数想调用 C++ std 函数的话,就可以加上 std::
。如以下代码:
class BigInteger
{
// ...
public:
void rand()
{
int n = std::rand(); //调用的是 cstdlib 中的 rand,而不是 BigIntegr::rand
rand(); //调用的是 BigInteger::rand(),会发生递归
}
void foo()
{
rand(); //调用的是 BigInteger::rand();
}
}
# 作用域分解
背景是这样的:在 ctype.h
中定义了 isspace
,而在 locale
中定义了 std::isspace
。
如果我们在前面定义了 using namespace std;
,isspace
会指向 std::isspace
。如果我们想调用 ctype.h
的 isspace
呢?就需要进行作用域分解:
::isspace
对,在作用域分辨符 ::
前什么都不加,就起到了分解作用域的作用。