名称空间特性
c++中要求可以通过定义一种新的声明区域来创建命名空间,这样目的之一就是提供一个声明名称的区域。一个名称区域中的名称不会与另外一个名称空间的相同名称发生冲突,同时允许程序中的其他部分使用该名称访问空间中声明的东西
使用namespace建立命名空间的栗子:
namespace Jack
{
double a;
void fetch();
struct Hell
{
};
}
namespace Jill
{
int Hell;
char fetch;
struct a
{
};
}
命名空间中内容的访问
访问命名空间中的名称,可以通过域解析运算符::,使用名称空间来限定该名称
Jack::a = 1.2;
Jill::Hell = 5;
我们还可以使用using,来简化每次都要限定的操作,using分为两种:using 声明和using 编译指令
using声明
using Jack::a;
using Jill::Hell;
使用using声明只能声明名称空间中的某一个变量或者函数,并且既可以将名称声明在局部声明区域也可以将名称添加到全局名称空间中
using编译指令
using namespace Jill;
using namespace Hill;
和using声明不同的是:using编译指令使名称空间中的所有名称都可用;和using声明相同的是:using既可以将名称声明在局部声明区域也可以将名称声明在全局声明区域中 。
using声明和using编译指令区别
#include <iostream>
using namespace std;
namespace Jill
{
double buckey(double n){}
double fetch;
}
char fetch; //全局变量
int main()
{
using namespace Jill;
double fetch; //局部变量,使用using编译指令时,如果出现命名冲突,则局部版本内容将隐藏名称空间内容
cin >> fetch; //局部变量内容
cin >> ::fetch; //通过作用域解析符获取全局变量内容
cin>>Jill::fetch; //名称空间中的数值
using Jill::fetch;
//double fetch; //如果using声明,如果定义了相同的名称,则两个名称会发生冲突,此时定义局部变量将会报错
cin>>fetch; //输入为名称空间中的数值
cin>>::fetch; //全局变量的数值
}
namespace中细节注意
首先需要知道,c++提供两种变量声明:一、定义,给变量分配存储空间;二、声明,不给变量分配存储空间,引用已有变量,关键字为:extern
c++中只能有一个变量的定义,其余的只能为变量的引用
当使用.cpp文件对命名空间.h文件进行函数具体化时,如果.h文件存在变量的定义,这里会出现变量重定义:
解决方法以及产生原因均在程序注释:
/*
namesp.h文件
*/
#ifndef NAMESP_H_INCLUDED
#define NAMESP_H_INCLUDED
#include <string>
namespace per
{
struct Person
{
std::string fname;
std::string lname;
};
void getPersion(Person &);
void showPerson(const Person &);
}
namespace debts
{
using namespace per;
struct Debt
{
Person name;
double amount;
};
extern double fetch; //这里一定为引用,因为namesp.h文件编译时,会找到namesp.cpp文件一起编译,如果使用定义的话,会在namesp.cpp和main.cpp文件中
//各包含一次,产生名称定义冲突,所以这里要将变量的定义放在namesp.cpp文件中,这样只会包含变量一次
void getDebt(Debt &);
void showDebt(const Debt&);
double sumDebts(const Debt ar[], int n);
}
#endif // NAMESP_H_INCLUDED
/*
namesp.cpp文件
*/
#include <iostream>
#include "namesp.h"
namespace per
{
using std::cout;
using std::cin;
void getPersion(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
{
double fetch;
void getDebt(Debt &rd)
{
getPersion(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 totle = 0;
for (int i = 0; i < n; i++)
totle += ar[i].amount;
return totle;
}
}
/*
main.cpp文件
*/
#include <iostream>
#include "namesp.h"
void other(void);
void another(void);
int main()
{
using debts::Debt;
using debts::showDebt;
Debt golf = { { "Benny","Goatsniff" },120.0 };
showDebt(golf);
other();
another();
return 0;
}
void other()
{
using std::cout;
using std::endl;
using namespace debts;
double fetch = 0;
cout << fetch << " " << &fetch << endl;
cout << debts::fetch << " " << &debts::fetch << endl;
//int repeat; 当名称空间和生命区定义了相同的名称,在使用using声明将命名空间的名称导入声明区域,则这两个名称会发生冲突
Person dg = { "Doodles","Gloster" };
showPerson(dg);
cout << endl;
Debt zippy[3];
for (int i = 0; i < 3; i++)
getDebt(zippy[i]);
for (int i = 0; i < 3; i++)
showDebt(zippy[i]);
cout << "Total debt:$" << sumDebts(zippy, 3) << endl;
return;
}
void another()
{
using per::Person;
Person collector = { "Milo","Rightshift" };
per::showPerson(collector);
std::cout << std::endl;
}
参考书籍
《c++ primer plus 第六版》