谈到 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;
}