■ UNNAMED NAMESPACESA compilation unit is a file, such as a class implementation file, along with all the files that are #included in the file, such as the interface header file for the
Trang 1Point 1 is pretty obvious Point 2 has some subtleties For example, suppose thenamespaces NS1 and NS2 both provide definitions for myFunction, but have no othername conflicts, then the following will produce no problems:
NS1::fun1( );
This form is often used when specifying a parameter type For example, considerint getInput(std::istream inputStream)
.
In the function getInput, the parameter inputStream is of type istream, where
istream is defined as in the std namespace If this use of the type name istream is theonly name you need from the std namespace (or if all the names you need are similarlyqualified with std::), then you do not need
using namespace std;
orusing std::istream;
Note that you can use std::istream even within the scope of a using directive foranother namespace which also defines the name istream In this case std::istream
and istream will have different definitions For example, considerusing namespace MySpace;
void someFunction(istream p1, std::istream p2);
using
directive
Trang 2void message( );
} namespace GoodBye {
void message( );
} void message( );
int main( ) {
using GoodBye::message;
{ using Hello::message;
message( );
GoodBye::message( );
} message( );
return 0;
} void message( ) {
cout << "Global message.\n";
} namespace Hello {
void message( ) {
Trang 3Example
cout << "Hello.\n";
} } namespace GoodBye {
void message( ) {
cout << "Good-Bye.\n";
} }
9 Write the declaration (prototype) for a void function named wow The function wow has two parameters, the first of type speed as defined in the speedway namespace and the sec-ond of type speed as defined in the indy500 namespace
A C LASS D EFINITION IN A N AMESPACE
In Displays 11.6 and 11.7 we have again rewritten both the header file dtime.h for the class talTime and the implementation file for the class DigitalTime This time (no pun intended),
Digi-we have placed the definition in a namespace called DTimeSavitch Note that the namespace
DTimeSavitch spans the two files dtime.h and dtime.cpp A namespace can span multiple files.
If you rewrite the definition of the class DigitalTime as shown in Displays 11.6 and 11.7, then the application file in Display 11.3 needs to specify the namespace DTimeSavitch in some way, such
as the following:
using namespace DTimeSavitch;
or
using DTimeSavitch::DigitalTime;
C HOOSING A N AME FOR A N AMESPACE
It is a good idea to include your last name or some other unique string in the names of your namespaces so as to reduce the chance that somebody else will use the same namespace name
as you do With multiple programmers writing code for the same project, it is important that namespaces that are meant to be distinct really do have distinct names Otherwise, you can easily have multiple definitions of the same names in the same scope That is why we included the name
Savitch in the namespace DtimeSavitch in Display 11.9.
Trang 4Display 11.6 Placing a Class in a Namespace (Header File)
1 //This is the header file dtime.h
Display 11.7 Placing a Class in a Namespace (Implementation File)
1 //This is the implementation file dtime.cpp.
in place of these four using declarations
However, the four using declarations are a preferable style.
Trang 5■ UNNAMED NAMESPACES
A compilation unit is a file, such as a class implementation file, along with all the files
that are #included in the file, such as the interface header file for the class Every pilation unit has an unnamed namespace A namespace grouping for the unnamednamespace is written in the same way as for any other namespace, but no name isgiven, as in the following example:
com-namespace {
void sampleFunction( ) .
} //unnamed namespace
All the names defined in the unnamed namespace are local to the compilation unit,and so the names can be reused for something else outside the compilation unit Forexample, Displays 11.8 and 11.9 show a rewritten (and final) version of the interface
compilation
unit
Display 11.8 Hiding the Helping Functions in a Namespace (Interface File) (part 1 of 2)
1 //This is the header file dtime.h This is the interface for the class DigitalTime.
2 //Values of this type are times of day The values are input and output in 24-hour
3 //notation, as in 9:30 for 9:30 AM and 14:45 for 2:45 PM.
19 void advance( int minutesAdded);
20 //Changes the time to minutesAdded minutes later.
This is our final version of the class DigitalTime
This is the best version and the one you should use
The implementation to use with this interface is given in Display 11.9.
Trang 6Display 11.8 Hiding the Helping Functions in a Namespace (Interface File) (part 2 of 2)
21 void advance( int hoursAdded, int minutesAdded);
22 //Changes the time to hoursAdded hours plus minutesAdded minutes later.
23 friend bool operator ==( const DigitalTime& time1,
24 const DigitalTime& time2);
25 friend istream& operator >>(istream& ins, DigitalTime& theObject);
26 friend ostream& operator <<(ostream& outs,
27 const DigitalTime& theObject);
Display 11.9 Hiding the Helping Functions in a Namespace (Implementation File) (part 1 of 3)
1 //This is the implementation file dtime.cpp of the class DigitalTime.
2 //The interface for the class DigitalTime is in the header file dtime.h.
17 //Uses iostream, cctype, and cstdlib:
18 void readMinute(int& theMinute)
24 cout << "Error: illegal input to readMinute\n";
Specifies the unnamed namespace
Names defined in the unnamed namespace are local to the compilation unit So, these helping functions are local to the file dtime.cpp.
Trang 7Display 11.9 Hiding the Helping Functions in a Namespace (Implementation File) (part 2 of 3)
35 //Uses iostream, cctype, and cstdlib:
36 void readHour( int & theHour)
Trang 8Display 11.9 Hiding the Helping Functions in a Namespace (Implementation File) (part 3 of 3)
63 cout << "Error: illegal input to readHour\n";
80 DigitalTime::DigitalTime( int theHour, int theMinute)
<The body of the function definition is the same as in Display 11.2.>
81 DigitalTime::DigitalTime( )
<The body of the function definition is the same as in Display 11.2.>
82 int DigitalTime::getHour( ) const
<The body of the function definition is the same as in Display 11.2.>
83 int DigitalTime::getMinute( ) const
<The body of the function definition is the same as in Display 11.2.>
84 void DigitalTime::advance( int minutesAdded)
<The body of the function definition is the same as in Display 11.2.>
85 void DigitalTime::advance( int hoursAdded, int minutesAdded)
<The body of the function definition is the same as in Display 11.2.>
86 } //DTimeSavitch
Within the compilation unit (in this case dtime.cpp), you can use names in the unnamed namespace without qualification.
Trang 9and implementation file for the class DigitalTime Note that the helping functions
readHour, readMinute, and digitToInt are all in the unnamed namespace; thus theyare local to the compilation unit As illustrated in Display 11.10, the names in theunnamed namespace can be reused for something else outside the compilation unit InDisplay 11.10, the function name readHour is reused for a different function in theapplication program
Display 11.10 Hiding the Helping Functions in a Namespace (Application Program) (part 1 of 2)
1 //This is the application file timedemo.cpp This program
2 //demonstrates hiding the helping functions in an unnamed namespace.
18 cout << "Something is wrong.";
19 cout << "You entered " << oldClock << endl;
20 cout << "15 minutes later the time will be "
21 << clock << endl;
22 clock.advance(2, 15);
23 cout << "2 hours and 15 minutes after that\n"
24 << "the time will be "
we wanted to give you an example of that technique.
This is a different function readHour than the one in the implementation file dtime.cpp (shown in Display 11.9).
Trang 10If you look again at the implementation file Display 11.9, you will see that the ing functions digitToInt, readHour, and readMinute are used outside the unnamednamespace without any namespace qualifier Any name defined in the unnamed name-space can be used without qualification anywhere in the compilation unit (Of course,this needed to be so, since the unnamed namespace has no name to use for qualifyingits names.)
help-It is interesting to note how unnamed namespaces interact with the C++ rule thatyou cannot have two definitions of a name in the same namespace There is oneunnamed namespace in each compilation unit It is easily possible for compilationunits to overlap For example, both the implementation file for a class and an applica-tion program using the class would normally both include the header file (interface file)for the class Thus, the header file is in two compilation units and hence participates intwo unnamed namespaces As dangerous as this sounds, it will normally produce noproblems as long as each compilation unit’s namespace makes sense when considered
by itself For example, if a name is defined in the unnamed namespace in the header
Display 11.10 Hiding the Helping Functions in a Namespace (Application Program) (part 2 of 2)
34 cout << "Let's play a time game.\n"
35 << "Let's pretend the hour has just changed.\n"
36 << "You may write midnight as either 0 or 24,\n"
37 << "but, I will always write it as 0.\n"
38 << "Enter the hour as a number (0 to 24): ";
39 cin >> theHour;
40 }
S AMPLE D IALOGUE
Let's play a time game.
Let's pretend the hour has just changed.
You may write midnight as either 0 or 24,
but, I will always write it as 0.
Enter the hour as a number (0 to 24): 11
You entered 11:00
15 minutes later the time will be 11:15
2 hours and 15 minutes after that
the time will be 13:30
When we gave these using declarations before, they were in main, so their scope was main Thus,
we need to repeat them here in order to use cin and cout in readHour.
Trang 11file, it cannot be defined again in the unnamed namespace in either the tion file or the application file Thus, a name conflict is avoided
implementa-C ONFUSING THE G LOBAL N AMESPACE AND THE U NNAMED N AMESPACE
Do not confuse the global namespace with the unnamed namespace If you do not put a name definition in a namespace grouping, then it is in the global namespace To put a name definition
in the unnamed namespace, you must put it in a namespace grouping that starts out as follows, without a name:
namespace {
Names in the global namespace and names in the unnamed namespace may both be accessed without a qualifier However, names in the global namespace have global scope (all the program files), whereas names in an unnamed namespace are local to a compilation unit
This confusion between the global namespace and the unnamed namespace does not arise very much in writing code, since there is a tendency to think of names in the global namespace as being “in no namespace,” even though that is not technically correct However, the confusion can easily arise when discussing code.
U NNAMED N AMESPACE
You can use the unnamed namespace to make a definition local to a compilation unit Each pilation unit has one unnamed namespace All the identifiers defined in the unnamed namespace are local to the compilation unit You place a definition in the unnamed namespace by placing the definition in a namespace grouping with no namespace name, as shown below:
com-namespace {
Definition_1
Definition_2
Definition_Last
}
You can use any name in the unnamed namespace without qualifiers anyplace in the compilation unit See Displays 11.8, 11.9, and 11.10 for a complete example.
Trang 12Tip
U NNAMED N AMESPACES R EPLACE THE static Q UALIFIER
Earlier versions of C++ used the qualifier static to make a name local to a file This use of stati c
is being phased out, and you should instead use the unnamed namespace to make a name local
to a compilation unit Note that this use of static has nothing to do with the use of static to qualify class members (as discussed in the subsection “Static Members” of Chapter 7 ) So, since
static used to mean more than one thing, it is probably good that one use of the word is being phased out.
H IDING H ELPING F UNCTIONS
There are two good ways to hide a helping function for a class You can make the function a private member function of the class or you can place the helping function in the unnamed namespace for the implementation file of the class If the function naturally takes a calling object, then it should be made a private member function If it does not naturally take a calling object, you can make it a static member function (for example, DigitalTime::readHour in Displays 11.1 and 11.2) or you can place it in the unnamed namespace of the implementation file (for exam- ple, readHour in Displays 11.8 and 11.9.)
If the helping function does not need a calling object, then placing the helping function in the unnamed namespace of the implementation file makes for cleaner code because it better sepa- rates interface and implementation into separate files and it avoids the need for so much function name qualification For example, note that in Display 11.9 we can use the function name read- Hour unqualified since it is in the unnamed namespace, while in the version in Display 11.2 we need to use DigitalTime::readHour
■ NESTED NAMESPACES
It is legal to nest namespaces When qualifying a name from a nested namespace, yousimply qualify twice For example, consider
namespace S1 {
namespace S2 {
void sample( ) {
}
Trang 13} //S2 }//S1
To invoke sample outside the namespace S1, you use
S1::S2::sample( );
To invoke sample outside the namespace S2 but within namespace S1, you use
S2::sample( );
Alternatively, you could use a suitable using directive
W HAT N AMESPACE S PECIFICATION S HOULD Y OU U SE ?
You have three ways to specify that your code uses the definition of a function (or other item) named f that was defined in a namespace named theSpace You can insert
using namespace theSpace;
Alternatively, you can insertusing theSpace::f;
Finally, you could omit the using directive altogether, but always qualify the function name by writing theSpace::f instead of just plain f
Which form should you use? All three methods can be made to work, and authorities differ on what they recommend as the preferred style However, to obtain the full value of namespaces, it is good to avoid the form
using namespace theSpace;
Placing such a using directive at the start of a file is little different than placing all definitions in the global namespace, which is what earlier versions of C++ actually did So, this approach gets no value from the namespace mechanism (If you place such a using directive inside a block, how- ever, then it only applies to that block This is another alternative, which is both sensible and advocated by many authorities.)
We prefer to use the second method most of the time, inserting statements like the following at the start of files:
using theSpace::f;
Trang 14Self-Test Exercises
This allows you to omit names that are in the namespace but that are not used That in turn avoids potential name conflicts Moreover, it nicely documents which names you use, and it is not as messy as always qualifying a name with notation of the form theSpace::f
If your files are structured so that different namespaces are used in different locations, it may sometimes be preferable to place your using directives and using declarations inside blocks, such as the bodies of function definitions, rather than at the start of the file.
10 Would the program in Display 11.10 behave any differently if you replaced the four using
using namespace DTimeSavitch;
11 What is the output produced by the following program?
#include <iostream>
using namespace std;
namespace Sally {
void message( );
} namespace {
void message( );
} int main( ) {
{ message( );
using Sally::message;
message( );
}
Trang 16namespace Outer {
void message( ) {
cout << "Outer.\n";
} namespace Inner {
void message( ) {
cout << "Inner.\n";
} } }
■ You can define a class and place the definition of the class and the implementation
of its member functions in separate files You can then compile the class separately from any program that uses it, and you can use this same class in any number of different programs
■ A namespace is a collection of name definitions, such as class definitions and able declarations
vari-■ There are three ways to use a name from a namespace: by making all the names in the namespace available with a using directive, by making the single name available with a using declaration for the one name, or by qualifying the name with the name
of the namespace and the scope resolution operator
■ You place a definition in a namespace by placing the definition in a namespace grouping for that namespace
■ The unnamed namespace can be used to make a name definition local to a tion unit
compila-ANSWERS TO SELF-TEST EXERCISES
1 Parts a, b, and c go in the interface file; parts d through h go in the implementation file (All the definitions of class operations of any sort go in the implementation file.) Part i (that is, the
main part of your program) goes in the application file
2 The name of the interface file ends in .h
3 Only the implementation file needs to be compiled The interface file does not need to be compiled
Chapter Summary
Trang 174 Only the implementation file needs to be recompiled You do, however, need to relink the files.
5 You need to delete the private member variables hour and minute from the interface file shown in Display 11.1 and replace them with the member variable minutes (with an s) You do not need to make any other changes in the interface file In the implementation file, you need to change the definitions of all the constructors and other member functions, as well as the definitions of the overloaded operators, so that they work for this new way of recording time (In this case, you do not need to change any of the helping functions
readHour, readMinute, or digitToInt, but that might not be true for some other class
or even some other reimplementation of this class.) For example, the definition of the loaded operator, >>, could be changed to the following:
over-istream& operator >>(istream& ins,
6 No If you replace bigGreeting with greeting, you will have a definition for the name
greeting in the global namespace There are parts of the program where all the name initions in the namespace Space1 and all the name definitions in the global namespace are simultaneously available In those parts of the program, there would be two distinct defini-tions for
def-void greeting( );
7 Yes The additional definition would cause no problems because overloading is always allowed When, for example, the namespace Space1 and the global namespace are avail-able, the function name greeting would be overloaded The problem in Self-Test Exer-cise 6 was that there would sometimes be two definitions of the function name greeting
with the same parameter lists
Trang 1810 The program would behave exactly the same However, most authorities favor using the
using declaration, as we have done in Display 11.10 Note that with either, there are still two different functions named readHour The one in Display 11.10 is different from the one defined in the unnamed namespace in Display 11.9
11.Hello from unnamed.
Hello from Sally.
Hello from unnamed.
develop-cout <<" Function_Name called" << endl;
where Function_Name is the name of the particular function In another file, main.cpp, put your main function, #include the minimum collection of files to provide access to the names from namespace A In your main function call the functions f then g Compile, link, and execute using your development environment To provide access to names in namespaces, you may use local using declarations such as:
Trang 192 Obtain the source code for the PFArrayD class and the demonstration program from plays 10.10, 10.11, and 10.10 Modify this program to use namespaces and separate com-pilation Put the class definition and other function declarations in one file Place the implementations in a separate file Distribute the namespace definition across the two files Place the demonstration program in a third file To provide access to names in namespaces, you may use local using declarations such as:
using namespace std;
3 Extend the Programming Project 1 from Chapter 10 in which you implemented a two dimensional array class by placing the class definition and implementation in a namespace, then providing access to the names in the namespace Test your code To provide access to names in namespaces, you may use local using declarations such as
Trang 2012 Streams and File I/O
12.1 I/O STREAMS 501
File I/O 501 Pitfall: Restrictions on Stream Variables 506 Appending to a File 506
Tip: Another Syntax for Opening a File 508 Tip: Check That a File Was Opened Successfully 509 Character I/O 512
Checking for the End of a File 513
12.2 TOOLS FOR STREAM I/O 517
File Names as Input 517 Formatting Output with Stream Functions 518 Manipulators 521
Saving Flag Settings 523 More Output Stream Member Functions 524 Example: Cleaning Up a File Format 525 Example: Editing a Text File 528
12.3 STREAM HIERARCHIES: A PREVIEW OF INHERITANCE 528
Inheritance among Stream Classes 528 Example: Another newLine Function 533
12.4 Random Access to Files 536
CHAPTER SUMMARY 538 ANSWERS TO SELF-TEST EXERCISES 539 PROGRAMMING PROJECTS 541