名称空间
C++为了防止两个相同名称相冲突,通过定义一种新的声明区域来创建命名的名称空间。
说明
- 任何名称空间中的名称都不会与其他名称空间中的名称发生冲突。
// 创建Student和Teacher两个名称空间,Student和Teacher中相同名称互不冲突。
namespace Student
{
char name[40]; // 变量
void func(); // 函数
struct Person {...}; // 结构体
}
namespace Teacher
{
char name[40]; // 变量
void func(); // 函数
struct Person {...}; // 结构体
}
// 定义时也需要在名称空间中
namespace Student
{
void func()
{
// ...
}
}
namespace Teacher
{
void func()
{
// ...
}
}
- 名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。
// 名称空间的嵌套
namespace animal
{
namespace bird
{
int a;
}
int b;
}
下面代码是错误的,因为名称空间不能位于代码块中
// 错误,因为名称空间不能位于代码块中
int main()
{
namespace animal
{
}
}
- 名称空间是开放的,可以把名称加入到已有的名称空间中。
namespace Student
{
char name[40]; // 变量
void func(); // 函数
struct Person {...}; // 结构体
}
namespace Student
{
int id;
void set_name(const char *);
}
- 通过作用域解析运算符 :: 来访问名称空间中的名称。
const char *name = Student::name; // 使用变量
Teacher::Person per; // 使用结构体
Student::func(); // 使用函数
using 的使用
如果不想每次使用变量时都加名称空间,可以使用using指令。
using std::cout; // 可以直接使用cout代替std::cout
using Student::name; // 可以直接使用name代替Student:name
也可以使用using指令使所有名称都可用
using namespace std; // std中的名称都可以直接使用
using namespace Student; // Student中的名称都可以直接使用
注意
使用using
指令会增加名称冲突的可能性。
using Student::func(); // 可以直接使用Student中的func()函数
using Teacher::func(); // 可以直接使用Teacher中的func()函数
using namespace Student; // 使Student中的所有名称都可以使用
using namespace Teacher; // 使Teacher中的所有名称都可以使用
现在Student和Teacher两个名称空间的相同名称就会产生冲突了。
全局变量、局部变量和名称空间中的变量一起使用
#include <iostream>
#include <string>
using namespace std;
// 名称空间
namespace Student
{
string name; // 使用string类型的字符串
double average;
void func();
}
char average; // 全局变量
int main()
{
using namespace Student; // 在main函数中Student中的所有名称可以直接使用
// using Student::average; // 使用using导入一个名称,会产生冲突
func(); // 使用Student中的函数
double average; // 正确,将会隐藏Student中的average
average = 3.14; // 局部变量
::average = 'p'; // 全局变量
Student::average = average * 2; // 名称空间中的变量
cout << "local average: " << average << endl;
cout << "global average: " << ::average << endl;
cout << "Student average: " << Student::average << endl;
}
namespace Student
{
void func()
{
cout << "Say hello" << endl;
}
}
注意
- 如果名称空间和声明区域定义了相同的名称,如果使用using指令导入某一个名称到该声明区中,则这两个名称会发生冲突。
- 如果使用using namespace将一个名称空间中的所有名称都导入该声明区,则局部的名称会隐藏名称空间中的名称。
- 如果也有全局的名称,则通过 ::global_variable 可以使用全局的名称。
名称空间的其他用法
- 可以将一个名称空间嵌套到另一个名称空间
namespace animal
{
namespace bird
{
int a;
}
int b;
}
- 可以给名称空间取别名
namespace p_stu = Person::Student; // 给Student取别名
- 匿名名称空间
namespace
{
int ice;
int bandycoot;
}
匿名名称空间不能使用using指令导入。不能在匿名名称空间所属文件之外的其他文件中使用,有点像静态变量。
#include <iostream>
using namespace std;
// 匿名名称空间,只能在本文件中使用
namespace
{
int ice;
int bandycoot;
}
namespace Doctor
{
int id;
int age;
}
namespace Person
{
using namespace Doctor;
namespace Student
{
int id;
}
namespace Teacher
{
int id;
}
int feature;
}
int main()
{
namespace p_stu = Person::Student; // 给Student取别名
p_stu::id = 20;
cout << "student id: " << p_stu::id << endl;
using namespace Person; // 与using namespace Doctor; 等价
// using namespace Doctor;
id = 10;
cout << "doctor id = " << id << endl;
// 匿名名称空间可以直接使用
ice = 100;
bandycoot = 200;
cout << "ice: " << ice << endl;
cout << "bandycoot: " << bandycoot << endl;
return 0;
}
程序说明
- 给
Person::Student
取了别名p_stu
,所以p_stu直接代表了Student。 using namespace Person;
等价于using namespace Doctor;
因为在Person这个名称空间中有using namespace Doctor;
- 匿名名称空间中的名称可以直接使用。