在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字就是针对这种问题而出现的。
一.传统名称空间
- 声明区域: 可以在其中进行声明的区域。 例如:可以在函数外面声明全局变量,对于这种变量,其声明区域为其声明所在的文件中。对于在函数中声明的变量,其声明区域为其声明所在的代码块.
- 潜在作用域: 变量的潜在作用域从声明点开始,到其声明区域的结尾。 因此潜在作用域比声明区域小,这是由于变量必须定义后才能使用。
- 作用域: 变量对程序而言可见的范围被称为作用域
二.新名称空间
通过定义一种新的声明区域来创建命名的名称空间
2.1有两种形式命名空间
有名的命名空间:
namespace 命名空间名 {
声明序列可选
}
匿名的命名空间:
namespace {
声明序列可选
}
eg:利用namespace创建两个名称空间
namespace Jack {
double pail; //变量声明
void fetch(); //函数原型
int pal; //变量声明
struct Well{
...}; //结构声明
}
namespace Jill {
double bucket(double n){
...} //函数定义
double fetch; //变量声明
int pal; //变量声明
struct Hill{
...}; //结构声明
}
需要有一种方法来访问给定名称空间中的名称。 最简单的方法是,通过作用域解析运算符::,使用名称空间来限定该名称。
Jack::pail = 12.34; //使用一个变量
Jill::Hill mole; //创造一个Hill类型结构
Jack::fetch(); //使用一个函数
2.2.命名空间可嵌套:
namespace A {
int a = 1000;
namespace B {
int a = 2000;
}
}
void test03()
{
cout<<"A中的a = "<<A::a<<endl; //1000
cout<<"B中的a = "<<A::B::a<<endl; //2000
}
一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
2.3. 无名命名空间,意味着命名空间中的标识符只能在本文件内访问,相当于给这个标识符加上了static,使得其可以作为内部连接
namespace{
int a =10;
void func(){
cout << "hello namespace "<< endl}
}
void test(){
cout << "a:" << a << endl;
func();
}
2.4.命名空间是开放的,即可以随时把新的成员加入已有的命名空间中(常用)
namespace A {
int a = 100;
int b = 200;
}
//将c添加到已有的命名空间A中
namespace A {
int c = 300;
}
void test04()
{
cout<<"A中a = "<<A::a<<endl;//100
cout<<"A中c = "<<A::c<<endl;//200
}
2.5 命名空间 可以存放 变量 和 函数
namespace A {
int a=100;//变量
void func()//函数
{
cout<<"func遍历a = "<<a<<endl;
}
}
void test05()
{
//变量的使用
cout<<"A中的a = "<<A::a<<endl;
//函数的使用
A::func();
}
三.
-
using声明和using编译指令
using声明由被限定的名称和它前面的关键字using组成
using Jill::fetch;
using编译指令由名称空间名和它前面的关键字using namespace组成(它使名称空间中的所有名称都可用,而不需要使用作用域解析运算符)
using namespace Jack;
-
在全局声明区域中使用using编译指令,使该名称空间的名称全局可用
#include <iostream>
using namespace std
四.名称空间示例
1.头文件包含:常量,结构定义和函数原型
//namesp.h
#include<string>
//创造名称空间pers和debts
namespace pers
{
struct Person {
std::string fname;
std::string lname;
};
void getPerson(Person &); //用人名填充结构
void showPerson(const Person &); //显示结构内容
}
namespace debts
{
using namespace pers;
struct Debt //储存人名和金额
{
Person name;
double amount;
};
void getDebt(Debt &);
void showDebt(const Debt &);
double sumDebts(const Debt ar[], int n);
}
2.源代码文件,提供头文件中的函数原型对应的定义
//namesp.cpp -- namespaces
#include<iostream>
#include "namesp.h"
namespace pers
{
using std::cout;
using std::cin;
void getPerson(Person &rp) //提供头文件中的函数原型对应的定义
{
cout << "Enter first name: ";
cin >> rp.fname;
cout << "Enter last name: ";
cin >> rp.lname;
}
void showPerson(const Person &rp)
{
cout << rp.lname << ", " << rp.fname;
}
}
namespace debts
{
void getDebt(Debt & rd)
{
getPerson(rd.name);
std::cout << "Enter debt: ";
std::cin >> rd.amount;
}
void showDebt(const Debt & rd)
{
showPerson(rd.name);
std::cout << ": $" <<rd.amount << std::endl;
}
double sumDebts(const Debt ar[], int n)
{
double total = 0;
for (int i = 0; i < n; i++)
total += ar[i].amount;
return total;
}
}
3.源代码文件,使用名称空间中声明和定义的结构和函数
//usenmsp.cpp -- using namespace
#include<iostream>
#include"namesp.h"
void other(void);
void another(void);
int main(void)
{
using debts::Debt;
using debts::showDebt;
Debt golf = {
{
"Benny","Goatsniff"},120.0 };
showDebt(golf);
other();
another();
std::cin.get();
std::cin.get();
return 0;
}
void other(void)
{
using std::cout;
using std::endl;
using namespace debts;
Person dg = {
"Doodles","Glister" };
showPerson(dg);
cout << endl;
Debt zippy[3];
int i;
for (i = 0; i < 3; i++)
getDebt(zippy[i]);
for (i = 0; i < 3; i++)
showDebt(zippy[i]);
cout << "Total debt: $" << sumDebts(zippy, 3) << endl;
return;
}
void another(void)
{
using pers::Person;
Person collector = {
"Milo","Rightshift" };
pers::showPerson(collector);
std::cout << std::endl;
}