For example, the function declaration and function definition in the namespace Space1 can be made available with the using directive using namespace Space1 as illustrated in Display 11.5
Trang 1Note that you can have any number of these namespace groupings for a single namespace In Display 11.5, we used two namespace groupings for namespace Space1
and two other groupings for namespace Space2
Every name defined in a namespace is available inside the namespace groupings, but the names can also be made available to code outside the namespace groupings For example, the function declaration and function definition in the namespace Space1 can
be made available with the using directive
using namespace Space1
as illustrated in Display 11.5
Display 11.5 Namespace Demonstration (part 2 of 2)
26
27 namespace Space1
28 {
29 void greeting( )
30 {
31 cout << "Hello from namespace Space1.\n";
32 }
33 }
34 namespace Space2
35 {
36 void greeting( )
37 {
38 cout << "Greetings from namespace Space2.\n";
39 }
40 }
41 void bigGreeting( )
42 {
43 cout << "A Big Global Hello!\n";
44 }
S AMPLE D IALOGUE
Greetings from namespace Space2.
Hello from namespace Space1.
A Big Global Hello!
Trang 2Self-Test Exercises
6 Consider the program shown in Display 11.5 Could we use the name greeting in place
of bigGreeting?
7 In Exercise 6, we saw that you could not add a definition for the following function to the
global namespace:
void greeting( );
Can you add a definition for the following function declaration to the global namespace? void greeting( int howMany );
This subsection describes a way to qualify a single name so that you can make only one name from a namespace available to your program, rather than making all the names in
a namespace available We saw this technique in Chapter 1 and so this is a review and amplification of what we said in Chapter 1
Suppose you are faced with the following situation You have two namespaces, NS1
and NS2 You want to use the function fun1 defined in NS1 and the function fun2
defined in namespace NS2 The complication is that both NS1 and NS2 also define a function myFunction (Assume all functions in this discussion take no arguments, so overloading does not apply.) There is a problem with
using namespace NS1;
using namespace NS2;
PUTTING A DEFINITION IN A NAMESPACE
You place a name definition in a namespace by placing it in a namespace grouping, which has the following syntax:
namespace Namespace_Name
{ Definition_1
Definition_2
Definition_Last
}
You can have multiple namespace groupings (even in multiple files), and all the definitions in all the groupings will be in the same namespace.
Trang 3This would potentially provide conflicting definitions for myFunction (If the name
myFunction is never used, then most compilers will not detect the problem and will
allow your program to compile and run.)
What you need is a way to say you are using fun1 in namespace NS1 and fun2 in
namespace NS2 and nothing else in the namespaces NS1 and NS2 We have already been
using a technique that can handle this situation The following is your solution:
using NS1::fun1;
using NS2::fun2;
A qualification of the form
using Name_Space :: One_Name ;
makes the (definition of the) name One_Name from the namespace Name_Space available, but
does not make any other names in Name_Space available This is called a using declaration.
Note that the scope resolution operator :: that we use in these using declarations is
the same as the scope resolution operator we use when defining member functions
These two uses of the scope resolution operator have a similarity For example, Display
11.2 had the following function definition:
void DigitalTime::advance(int hoursAdded, int minutesAdded)
{
hour = (hour + hoursAdded)%24;
advance(minutesAdded);
}
In this case the :: means that we are defining the function advance for the class
Digi-talTime, as opposed to any other function named advance in any other class Similarly,
using NS1::fun1;
means we are using the function named fun1 as defined in the namespace NS1, as
opposed to any other definition of fun1 in any other namespace
There are two differences between a using declaration, such as
using std::cout;
and a using directive such as
using namespace std;
The differences are:
1 A a using declaration makes only one name in the namespace available to your
code, while a using directive makes all the names in a namespace available
2 A using declaration introduces a name (like cout) into your code so no other use of
the name can be made However, a using directive only potentially introduces the
names in the namespace
using NS1::fun1;
using
declaration
Trang 4Point 1 is pretty obvious Point 2 has some subtleties For example, suppose the namespaces NS1 and NS2 both provide definitions for myFunction, but have no other name conflicts, then the following will produce no problems:
using namespace NS1;
using namespace NS2;
provided that (within the scope of these directives) the conflicting name myFunction is never used in your code
On the other hand, the following is illegal, even if the function myFunction is never used: using NS1::myFunction;
using NS2::myFunction;
Sometimes this subtle point can be important, but it does not impinge on most rou-tine code So, we will often use the term using directive loosely to mean either a using
directive or a using declaration
This section introduces a way to qualify names that we have not discussed before Suppose that you intend to use the name fun1 as defined in the namespace NS1, but you only intend to use it one time (or a small number of times) You can name the function (or other item) using the name of the namespace and the scope resolution operator as follows:
NS1::fun1( );
This form is often used when specifying a parameter type For example, consider int 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 the only name you need from the std namespace (or if all the names you need are similarly qualified with std::), then you do not need
using namespace std;
or using std::istream;
Note that you can use std::istream even within the scope of a using directive for another namespace which also defines the name istream In this case std::istream
and istream will have different definitions For example, consider using namespace MySpace;
void someFunction(istream p1, std::istream p2);
using
directive
Trang 5Self-Test Exercises
Assuming istream is a type defined in the namespace MySpace, then p1 will have the type istream as defined in MySpace and p2 will have the type istream as defined in the
std namespace
8 What is the output produced by the following program?
#include <iostream>
using namespace std;
namespace Hello {
void 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 6Example
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 Digi-talTime and the implementation file for the class DigitalTime This time (no pun intended),
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 7Display 11.6 Placing a Class in a Namespace (Header File)
1 //This is the header file dtime.h
2 #ifndef DTIME_H
3 #define DTIME_H
4 #include <iostream>
5 using std::istream;
6 using std::ostream;
7 namespace DTimeSavitch
8 {
9
10 class DigitalTime
11 {
12
13 <The definition of the class DigitalTime is the same as in Display 11.1.>
14 };
15
16 }// DTimeSavitch
17 #endif //DTIME_H
A better version of this class definition will be given in Displays 11.8 and 11.9.
Note that the namespace DTimeSavitch spans two files The other is shown in Display 11.7.
Display 11.7 Placing a Class in a Namespace (Implementation File)
1 //This is the implementation file dtime.cpp.
2 #include <iostream>
3 #include <cctype>
4 #include <cstdlib>
5 using std::istream;
6 using std::ostream;
7 using std::cout;
8 using std::cin;
9 #include "dtime.h"
10 namespace DTimeSavitch
11 {
12
13 <All the function definitions from Display 11.2 go here.>
14
15 }// DTimeSavitch
You can use the single using directive using namespace std;
in place of these four using declarations
However, the four using declarations are a preferable style.
Trang 8■ 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 com-pilation unit has an unnamed namespace A namespace grouping for the unnamed namespace is written in the same way as for any other namespace, but no name is given, as in the following example:
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 For example, 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.
4 #ifndef DTIME_H
5 #define DTIME_H
6 #include <iostream>
7 using std::istream;
8 using std::ostream;
9 namespace DTimeSavitch
10 {
11 class DigitalTime
12 {
13 public :
14 DigitalTime( int theHour, int theMinute);
15 DigitalTime( );
16 //Initializes the time value to 0:00 (which is midnight).
17 getHour( ) const ;
18 getMinute( ) const ;
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 9Display 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);
28 private :
29 int hour;
30 int minute;
31 };
32 } //DTimeSavitch
33 #endif //DTIME_H
Note that the helping functions are not mentioned in the interface file
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.
3 #include <iostream>
4 #include <cctype>
5 #include <cstdlib>
6 using std::istream;
7 using std::ostream;
8 using std::cout;
9 using std::cin;
10 #include "dtime.h"
11 namespace
12 {
13 int digitToInt( char c)
14 {
15 return ( int (c) - int (’0’) );
16 }
17 //Uses iostream, cctype, and cstdlib:
18 void readMinute(int& theMinute)
19 {
20 char c1, c2;
21 cin >> c1 >> c2;
22 if (!(isdigit(c1) && isdigit(c2)))
23 {
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 10Display 11.9 Hiding the Helping Functions in a Namespace (Implementation File) (part 2 of 3)
25 exit(1);
26 }
27 theMinute = digitToInt(c1)*10 + digitToInt(c2);
28 if (theMinute < 0 || theMinute > 59)
29 {
30 cout << "Error: illegal input to readMinute\n";
31 exit(1);
32 }
33 }
34
35 //Uses iostream, cctype, and cstdlib:
36 void readHour( int & theHour)
37 {
38 char c1, c2;
39 cin >> c1 >> c2;
40 if ( !( isdigit(c1) && (isdigit(c2) || c2 == ’:’ ) ) )
41 {
42 cout << "Error: illegal input to readHour\n";
43 exit(1);
45 if (isdigit(c1) && c2 == ’:’)
46 {
47 theHour = digitToInt(c1);
48 }
49 else //(isdigit(c1) && isdigit(c2))
51 theHour = digitToInt(c1)*10 + digitToInt(c2);
52 cin >> c2; //discard ’:’
53 if (c2 != ’:’)
54 {
55 cout << "Error: illegal input to readHour\n";
56 exit(1);
59 if (theHour == 24)
60 theHour = 0; //Standardize midnight as 0:00.
61 if ( theHour < 0 || theHour > 23 )
62 {