Namespaces and the Future

As programmers become more familiar with namespaces, common programming idioms will emerge. Here are some current guidelines:

• Use variables in a named namespace instead of using external global variables.

• Use variables in an unnamed namespace instead of using static global variables.

• If you develop a library of functions or classes, place them in a namespace. Indeed, C++ currently already calls for placing standard library functions in a namespace called std. This extends to functions brought in from C. For example, the math.c header file, which is C-compatible, doesn’t use namespaces, but the C++ cmath header file should place the various math library functions in the std namespace.

• Use the using directive only as a temporary means of converting old code to namespace usage.

• Don’t use using directives in header files; for one thing, doing so conceals which names are being made available. Also the ordering of header files may affect behavior. If you use a using directive, place it after all the preprocessor #include directives.

• Preferentially import names by using the scope-resolution operator or a using declaration.

• Preferentially use local scope instead of global scope for using declarations.

Bear in mind that the main motivation for using namespaces is to simplify management of large programming projects. For simple, one-file programs, using a using directive is no great sin.

As mentioned earlier, changes in the header filenames reflect namespace changes. The older-style header files, such as iostream.h, do not use namespaces, but the newer iostream header file should use the std namespace.

Summary

C++ encourages the use of multiple files in developing programs. An effective organizational strategy is to use a header file to define user types and provide function prototypes for functions to manipulate the user types. You should use a separate source code file for the function definitions. Together, the header file and the source file define and implement the user-defined type and how it can be used. Then, main() and other functions using those functions can go into a third file.

C++’s storage schemes determine how long variables remain in memory (storage duration) and what parts of a program have access to them (scope and linkage). Automatic variables are variables that are defined within a block, such as a function body or a block within the body. They exist and are known only while the program executes statements in the block that contains the definition. Automatic variables may be declared by using the storage class specifier register or with no specifier at all, in which case the variable is automatically automatic. The register specifier was a hint to the compiler that the variable is heavily used, but that use is deprecated under C++11.

Static variables exist for the duration of a program. A variable defined outside any function is known to all functions in the file following its definition (file scope) and is made available to other files in the program (external linkage). For another file to use such a variable, that file must declare it by using the extern keyword. A variable that is shared across files should have a defining declaration in one file (extern needn’t be used but it can be used if combined with initialization) and reference declarations in the other files (extern is used with no initialization.). A variable defined outside any function but qualified with the keyword static has file scope but is not made available to other files (internal linkage). A variable defined inside a block but qualified with the keyword static is local to that block (local scope, no linkage) but retains its value for the duration of the program.

By default, C++ functions have external linkage, so they can be shared across files. But functions qualified with the keyword static have internal linkage and are confined to the defining file.

Dynamic memory allocation and deallocation, using new and delete, uses the free store, or heap, for data. The memory comes into use when new is called and is freed when delete is called. The program uses pointers to keep track of these memory locations.

Namespaces let you define named regions in which you can declare identifiers. The intent is to reduce name conflicts, particularly in large programs that use code from several vendors. You can make available identifiers in a namespace by using the scope-resolution operator, by using a using declaration, or by using a using directive.

Chapter Review

1. What storage scheme would you use for the following situations?

a. homer is a formal argument (parameter) to a function.

b. The secret variable is to be shared by two files.

c. The topsecret variable is to be shared by the functions in one file but hidden from other files.

d. beencalled keeps track of how many times the function containing it has been called.

2. Describe the differences between a using declaration and a using directive.

3. Rewrite the following so that it doesn’t use using declarations or using directives:

#include <iostream>
using namespace std;
int main()
{
    double x;
    cout << "Enter value: ";
    while (! (cin >> x) )
    {
        cout << "Bad input. Please enter a number: ";
        cin.clear();
       while (cin.get() != ' ')
           continue;
    }
    cout << "Value = " << x << endl;
    return 0;
}

4. Rewrite the following so that it uses using declarations instead of the using directive:

#include <iostream>
using namespace std;
int main()
{
    double x;
    cout << "Enter value: ";
    while (! (cin >> x) )
    {
        cout << "Bad input. Please enter a number: ";
        cin.clear();
       while (cin.get() != ' ')
           continue;
    }
    cout << "Value = " << x << endl;
    return 0;
}

5. Suppose you want the average(3,6) function to return an int average of the two int arguments when it is called in one file, and you want it to return a double average of the two int arguments when it is called in a second file in the same program. How could you set this up?

6. What will the following two-file program display?

// file1.cpp
#include <iostream>
using namespace std;
void other();
void another();
int x = 10;
int y;

int main()
{
    cout << x << endl;
    {
        int x = 4;
        cout << x << endl;
        cout << y << endl;
    }
    other();
    another();
    return 0;
}

void other()
{
    int y = 1;
    cout << "Other: " << x << ", " << y << endl;
}

// file 2.cpp
#include <iostream>
using namespace std;
extern int x;
namespace
{
    int y = -4;
}

void another()
{
    cout << "another(): " << x << ", " << y << endl;
}

7. What will the following program display?

#include <iostream>
using namespace std;
void other();
namespace n1
{
    int x = 1;
}

namespace n2
{
    int x = 2;
}


int main()
{
   using namespace n1;
   cout << x << endl;
    {
        int x = 4;
        cout << x << ", " << n1::x << ", " << n2::x << endl;
    }
    using n2::x;
    cout << x << endl;
    other();
    return 0;
}

void other()
{
    using namespace n2;
    cout << x << endl;
    {
        int x = 4;
        cout << x << ", " << n1::x << ", " << n2::x << endl;
    }
    using n2::x;
    cout << x << endl;
}

Programming Exercises

1. Here is a header file:

// golf.h -- for pe9-1.cpp

const int Len = 40;
struct golf
{
    char fullname[Len];
    int handicap;
};

// non-interactive version:
//  function sets golf structure to provided name, handicap
//  using values passed as arguments to the function
void setgolf(golf & g, const char * name, int hc);

// interactive version:
//  function solicits name and handicap from user
//  and sets the members of g to the values entered
//  returns 1 if name is entered, 0 if name is empty string
int setgolf(golf & g);

// function resets handicap to new value
void handicap(golf & g, int hc);

// function displays contents of golf structure
void showgolf(const golf & g);

Note that setgolf() is overloaded. Using the first version of setgolf() would look like this:

golf ann;
setgolf(ann, "Ann Birdfree", 24);

The function call provides the information that’s stored in the ann structure. Using the second version of setgolf() would look like this:

golf andy;
setgolf(andy);

The function would prompt the user to enter the name and handicap and store them in the andy structure. This function could (but doesn’t need to) use the first version internally.

Put together a multifile program based on this header. One file, named golf.cpp, should provide suitable function definitions to match the prototypes in the header file. A second file should contain main() and demonstrate all the features of the prototyped functions. For example, a loop should solicit input for an array of golf structures and terminate when the array is full or the user enters an empty string for the golfer’s name. The main() function should use only the prototyped functions to access the golf structures.

2. Redo Listing 9.9, replacing the character array with a string object. The program should no longer have to check whether the input string fits, and it can compare the input string to "" to check for an empty line.

3. Begin with the following structure declaration:

struct chaff
{
    char dross[20];
    int slag;
};

Write a program that uses placement new to place an array of two such structures in a buffer. Then assign values to the structure members (remembering to use strcpy() for the char array) and use a loop to display the contents. Option 1 is to use a static array, like that in Listing 9.10, for the buffer. Option 2 is to use regular new to allocate the buffer.

4. Write a three-file program based on the following namespace:

namespace SALES
{
    const int QUARTERS = 4;
    struct Sales
    {
        double sales[QUARTERS];
        double average;
        double max;
        double min;
    };
    // copies the lesser of 4 or n items from the array ar
    // to the sales member of s and computes and stores the
    // average, maximum, and minimum values of the entered items;
    // remaining elements of sales, if any, set to 0
    void setSales(Sales & s, const double ar[], int n);
    // gathers sales for 4 quarters interactively, stores them
    // in the sales member of s and computes and stores the
    // average, maximum, and minimum values
    void setSales(Sales & s);
    // display all information in structure s
    void showSales(const Sales & s);
}

The first file should be a header file that contains the namespace. The second file should be a source code file that extends the namespace to provide definitions for the three prototyped functions. The third file should declare two Sales objects. It should use the interactive version of setSales() to provide values for one structure and the non-interactive version of setSales() to provide values for the second structure. It should display the contents of both structures by using showSales().

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

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