当前位置:嗨网首页>书籍在线阅读

17-名称空间示例

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

9.3.3 名称空间示例

现在来看一个多文件示例,该示例说明了名称空间的一些特性。该程序的第一个文件(参见程序清单9.11)是头文件,其中包含头文件中常包含的内容:常量、结构定义和函数原型。在这个例子中,这些内容被放在两个名称空间中。第一个名称空间叫作pers,其中包含Person结构的定义和两个函数的原型——一个函数用人名填充结构,另一个函数显示结构的内容;第二个名称空间叫作debts,它定义了一个结构,该结构用来存储人名和金额。该结构使用了Person结构,因此,debts名称空间使用一条using编译指令,让pers中的名称在debts名称空间可用。debts名称空间也包含一些原型。

程序清单9.11 namesp.h

// namesp.h
#include <string>
// create the pers and debts namespaces
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);
}

第二个文件(见程序清单9.12)是源代码文件,它提供了头文件中的函数原型对应的定义。在名称空间中声明的函数名的作用域为整个名称空间,因此定义和声明必须位于同一个名称空间中。这正是名称空间的开放性发挥作用的地方。通过包含namesp.h(参见程序清单9.11)导入了原来的名称空间。然后该文件将函数定义添加入到两个名称空间中,如程序清单9.12所示。另外,文件names.cpp演示了如何使用using声明和作用域解析运算符来使名称空间std中的元素可用。

程序清单9.12 namesp.cpp

// 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)
    {
        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;
    }
}

最后,该程序的第三个文件(参见程序清单9.13)是一个源代码文件,它使用了名称空间中声明和定义的结构和函数。程序清单9.13演示了多种使名称空间标识符可用的方法。

程序清单9.13 namessp.cpp

// 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;
}
void another(void)
{
    using pers::Person;
    Person collector = { "Milo", "Rightshift" };
    pers::showPerson(collector);
    std::cout << std::endl;
}

在程序清单9.13中,main()函数首先使用了两个using声明:

using debts::Debt;     // makes the Debt structure definition available
using debts::showDebt; // makes the showDebt function available

注意,using声明只使用了名称,例如,第二个using声明没有描述showDebt的返回类型或函数特征标,而只给出了名称;因此,如果函数被重载,则一个using声明将导入所有的版本。另外,虽然Debt和showDebt都使用了Person类型,但不必导入任何Person名称,因为debt名称空间有一条包含pers名称空间的using编译指令。

接下来,other()函数采用了一种不太好的方法,即使用一条using编译指令导入整个名称空间:

using namespace debts; // make all debts and pers names available to other()

由于debts中的using编译指令导入了pers名称空间,因此other()函数可以使用Person类型和showPerson()函数。

最后,another()函数使用using声明和作用域解析运算符来访问具体的名称:

using pers::Person;;
pers::showPerson(collector);

下面是程序清单9.11~程序清单9.13组成的程序的运行情况:

Goatsniff, Benny: $120
Glister, Doodles
Enter first name: Arabella
Enter last name: Binx
Enter debt: 100
Enter first name: Cleve
Enter last name: Delaproux
Enter debt: 120
Enter first name: Eddie
Enter last name: Fiotox
Enter debt: 200
Binx, Arabella: $100
Delaproux, Cleve: $120
Fiotox, Eddie: $200
Total debt: $420
Rightshift, Milo