Imagine you've almost finished a program and you decide to add some nice graphics (plots and charts). No problem--you install a professional-looking graphing package and add some function calls to your program to execute the new package. Unfortunately, when you try to compile the application, you get errors that say multiple declarations were found for functions x, y, and z. After some investigation, you realize that both your code and the third-party package have x, y, and z functions. What do you do?
You have several choices (most of them bad). You can globally change all your function, variable, and class names to other, unique names. You can get the graphing package's source code and do the same to it. Or (drum roll, please), you can enclose your declarations within a namespace, which would effectively give all your identifiers unique names.
I programmed C and C++ for many years without using namespaces--I never had to. Only within the last couple years have I found myself putting them to work. As programming languages evolve, different constructs fall in and out of favor with the programming community. Lately, namespaces have seen a rise in popularity due in large part to the C++ Standard Template Library (STL), which uses them extensively. In this article, we'll look at how namespaces work, and explore when you should (or must!) put them to work.
A namespace delineates a block of code in which identifiers are unique from the rest of the code. Code outside the namespace block can still reference the variables, functions, or classes inside the block, but their full identifier names must be used.
The syntax of a namespace is simple. You declare the namespace block using the namespace keyword, followed by its name and an interior block of code:
namespace MySpace
{
int x;
float SomeFnc() { ... }
class SomeClass { ... };
}// end of MySpace namespace block
There's nothing special about the code inside a namespace--it's just like any
other code.
Unlike class and function blocks, explicit namespaces are concerned only with global identifiers. You can't declare explicit namespaces within a class or function. However, you can nest them, as shown in Listing A, or extend/continue them, as shown in Listing B.
Listing A: Nested namespaces
namespace SpaceA
{
int i;
float f;
namespace SpaceB
{
int i;
float f;
} // end of SpaceB
} // end of SpaceA
Listing B: Extended namespaces
namespace SpaceA
{
int i;
float f;
} // end of SpaceA
int i;
float f;
double d;
namespace SpaceA
{
double d;
}// end of SpaceA extension
float f = MySpace::SomeFnc() + MySpace::x;If such code gets to be too tedious (if you have to make many references to identifiers in the namespace), you can declare your intent to use the namespace for all references until further notice. You do so by placing the command using namespace xyz before the part of your program in which you need to reference the namespace code:
using namespace MySpace; . . . float f = SomeFnc() + x;This method saves you from repeatedly typing the name of the namespace. However, you may still need to use the full identifier name (including namespace) if it happens to be the same identifier used for a different purpose in another portion of the program.
using namespace MySpace;or add MySpace:: to the front of the identifier each time you use it. But, the best method may be to place
using namespace MySpace::SomeFunc;at the top of the module. This line will alert the compiler that any reference to SomeFunc() in that module should be mapped to MySpace::SomeFunc(). The rest of your code will be unaffected and will map to your identifiers.
XYZCOMPANY_FINACIAL_UTILITIES_NAMESPACEbefore each reference to a package's identifiers? You can shorten such a namespace to one of your own liking by writing the following code:
namespace XYZ = XYZCOMPANY_FINACIAL_UTILITIES_NAMESPACE;If the company's namespace doesn't depict the certain utilities you use from its package, give the namespace an alias that makes it easier for you to relate to. For example, if you use only a full-blown financial package for loan interest calculations, it may be easier to relate to the namespace if you alias it as follows:
namespace INT_CALC = XYZCOMPANY_FINACIAL_UTILITIES_NAMESPACE;
If you encounter a duplicate name, the simplest way out is to enclose all your header material within a namespace with a name that no one else would use (such as your initials or name). When the compiler goes through your code, it will prepend your namespace name to the front of all your identifiers when building its identifier list--for example,
int i;will become
int SomeSpace::i;Now, you'll have to reference the new identifier names a little differently. Simply place a using namespace command at the top of your implementation (CPP) file; all your identifier usages will be prepended with your namespace name. Presto, no more identifier conflicts!
To tell the compiler that you want to use a non-namespace identifier provided in the third-party package, you simply add the scope resolution operator (::) to the front of the third-party function call. Everything that isn't in a namespace is considered global and can be accessed this way.
| Tip: Save your users the same trouble |
|---|
| You should add explicit namespaces to your programs and utilities if other people will be using them. If you're producing a third-party product, using namespaces will protect the unsuspecting user from the dilemma of duplicate identifiers. |
The C++ STL is gaining popularity lately, and guess what? It's enclosed in a namespace called std. If you want to use any of the templates in the STL, you must become at least vaguely familiar with using namespace. The easiest way to reference the STL identifiers (vectors, lists, deques, and so on) is to place using namespace std; at the top of your module--a pretty painless task.