A Namespace Example

Let’s take a look at a multifile example that demonstrates some of the features of namespaces. The first file in this example (see Listing 9.11) is a header file that contains some items normally found in header files—constants, structure definitions, and function prototypes. In this case, the items are placed in two namespaces. The first namespace, pers, contains a definition of a Person structure, plus prototypes for a function that fills a structure with a person’s name and a function that displays the structure’s contents. The second namespace, debts, defines a structure for storing the name of a person and the amount of money owed to that person. This structure uses the Person structure, so the debts namespace has a using directive to make the names in the pers namespace available in the debts namespace. The debts namespace also contains some prototypes.

Listing 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);
}


The second file in this example (see Listing 9.12) follows the usual pattern of having a source code file provide definitions for functions prototyped in a header file. The function names, which are declared in a namespace, have namespace scope, so the definitions need to be in the same namespace as the declarations. This is where the open nature of namespaces comes in handy. The original namespaces are brought in by including namesp.h (refer to Listing 9.11). The file then adds the function definitions to the two namespaces, as shown in Listing 9.12. Also the namesp.cpp file illustrates bringing in elements of the std namespace with the using declaration and the scope-resolution operator.

Listing 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;
    }
}


Finally, the third file of this program (see Listing 9.13) is a source code file that uses the structures and functions declared and defined in the namespaces. Listing 9.13 shows several methods of making the namespace identifiers available.

Listing 9.13. usenmsp.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;
}


In Listing 9.13, main() begins by using two using declarations:

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

Note that using declarations just use the name; for example, the second example here doesn’t describe the return type or function signature for showDebt; it just gives the name. (Thus, if a function were overloaded, a single using declaration would import all the versions.) Also although both Debt and showDebt() use the Person type, it isn’t necessary to import any of the Person names because the debt namespace already has a using directive that includes the pers namespace.

Next, the other() function takes the less desirable approach of importing the entire namespace with a using directive:

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

Because the using directive in debts imports the pers namespace, the other() function can use the Person type and the showPerson() function.

Finally, the another() function uses a using declaration and the scope-resolution operator to access specific names:

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

Here is a sample run of the program built from Listings 9.11, 9.12, and 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

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.31.22