谈到 namespace 的具体使用,分两步来谈。
1)声明或定义一个 namespace
2) 对某个namespace 下的变量或函数具体调用。
首先来谈第一点:
下面具体来看两个 namespace 的声明(代码摘录于 C++ PrimerPlus, Fifth Edition, Page 426)
namespace Jack
{
double pail; // variable declaration
void fetch(); // function prototype
intpal; // variable declaration
struct Well{ ... }; // structure declaration
}
namespace Jill
{
double bucket(double n){ ... } // function definition
doublefetch; // variable declaration
intpal; // variable declaration
structHill{...}; // structure declaration
}
Namespaces 可以像设置全局变量一样设置,namespaces 可以嵌套与其他 namespaces中,但是namespaces 不可以设置于某个某个块中,即不可以局部设置于某个函数块中或独立的设置于 两个花括号之中。也就是说,一个位于namespace 中的变量或函数在默认情况下具有外部连接能力(除非他被指定为 const)
此外,namespace 是开放的,也就是说,你可以在 namespace 的声明或定义之外,添加代码,即添加变量以及函数。
比如
namespace Jill
{
char * goose(const char * ); // adds the name goose to the exiting list of names in Jill
}
通常的做法是我们将 namespace 的声明写入一个或多个头文件,将定义写入一个 cpp 或多个 cpp 文件
第二点, 对某个namespace 下的变量或函数具体调用:
最简单的做法是采用作用域操作符 ::
比如 Jack::pail = 12.34; // use a variable
Jill::Hill mole; // create a type Hill structure
Jack::fetch(); // use a function
此外必须提到的是 using Declarations and using Directives
由于使用作用域操作符的比较麻烦,因为它增加了你打字的工作,我想没几个人喜欢在每句cout 前增加 std:: 的。但是在某种情况下采用作用域的方法不可避免,这也是 姬老师 那个 抗议贴中提到的担心。 下面我也将提到。
a) using Declarations - 对namespace 下的具体变量以及函数声明调用。如:using Jill::fetch; // a using declaration
这样声明后,以后在程序中如出现 对变量 fetch 的操作将被认为是 Jill 那个namespace 下的 fetch, 如果在程序中Jill::fetch的作用域内再声明或定义同样名字的变量将被认为出错。下面的代码说明这个问题:
namespace Jill
{
double bucket(double n){ ... } // function definition
doublefetch; // variable declaration
intpal; // variable declaration
structHill{...}; // structure declaration
}
char fetch; // ok
int main()
{
using Jill::fetch; // put fetch into local namespace
double fetch; // Error! Already have a local fetch
cin>>fetch; // read a value into Jill::fetch
cin>>::fetch; // read a value into global fetch
......
return 0;
}
与此相比, using directive 使得整个namespace 下的变量以及函数成为有效调用。
比如如果在程序中这样写:
using namespace Jack;
cin>>pail;
fetch();
那么这里的pail, fetch() 将被认为是 Jack 名字空间下的变量和函数。
现在来谈 姬老师 所担心的那个歧义性:
在使用了 using directives 以及 使用了 using declarations 之后,随之也带来一个问题,那就是歧义性问题。
比如如下代码:
using Jack::pal;
using Jill::pal;
pal = 4; // which one? now have a conflict
但如果我们明确使用作用域符合,那么这样的歧义性就没有了。 如 Jill::pal= 4; // no conflict
下面摘入书上程序 listing 9.10, listing 9.11 以及 listing 9.12, 让大家感受一下 namespace 在程序中的使用。
// namesp.h
// create the pers and debts namespaces
namespace pers
{
const int LEN = 40;
struct Person
{
char fname[LEN];
char lname[LEN];
};
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);
}
// 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)
{
std::cout<<rp.lname<<", "<<rp.fname;
}
}
namespace debts
{
void getDebt(Debt & rd)
{
using namespace pers;
getPerson(rd.name); // hier ist merkwuerdig
std::cout<<"Enter debt: ";
std::cin>>rd.amount;
}
void showDebt(const Debt & rd)
{
pers::showPerson(rd.name); // hier ist merkwuerdig
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;
}
}
// usenmsp.cpp -- using namespaces
#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();
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 ; // Dieser return ist auch ueberfluessig
}
void another(void)
{
using pers::Person;;
Person collector = {"Milo", "Rightshift"};
pers::showPerson(collector);
std::cout<<std::endl;
}