In
C++, each
structure,
class, or
union has its own namespace.
Within that namespace,
member names will not conflict with other classes.
(This was not the case with very very early versions of
C, which is why
a lot of structures in the C standard library have their members prefixed with the struct name.)
Also, the 3rd edition of The C++ Programming Language introduces the
separate concept of namespace
as a keyword in its own right, which allows the programmer to assign an
identifier or group of identifiers to a namespace. This helps reduce global namespace pollution which the linker hates so much, especially when
there is a collision. Namespaces use the same
qualification syntax as classes , but the two are not interchangeable.
Namespaces are simpler, in that they only do encapsulation. Stroustrup
says1 they are better than classes when you
need namespace encapsulation, but don't
need type checking and object overhead provided by a class.
In C++ (post 1997), all of the libraries have their own namespaces.
The standard library lives in std:: of course. The standard C libraries are also
in the std:: namespace.
The using keyword allows you to alias an identifier into the current
scope; otherwise the namespace must be qualified for each use.
Single identifiers from a namespace can be imported this way, or the entire
namespace can be imported. If imported namespaces have overlapping
symbols, they must be resolved at compile time, rather than link time, and thus
symbol collision errors are caught sooner. The using keyword can clarify which
namespace's function is used, if the results are not as desired.
Note well that if you just import all the namespaces, you will be back where
you started, with the compiler complaining about ambiguous duplicate functions.
Unlike classes, namespaces are "open". The same namespace can be mentioned
in different places, adding symbols to it in each place.
Namespaces don't have to be named, just like enums don't have to be named.
The effect of an unnamed namespace is that the symbols in the namespace
will not be exported
out of this compilation unit. Global static has nearly the same effect in C,
but is depreciated in C++ in favor of namespaces. Global statics are mostly
to prevent name collisions between modules--and namespaces do this better.
Stroustrup2
also recommends giving namespaces long names that include version
numbers and full library names, and then using the namespace aliasing mechanism
to alias back to a short name that is more manageable. This way,
you can change which library you are using just by changing the namespace alias.
If a function is not found in the current namespace (and hasn't been imported
from another namespace), the compiler will search the namespaces of the
argument types to that function in hopes of finding a matching prototype.
Like many other resolution issues, this could seem magical.
For complex examples, check out a book. These examples should be enough to
help figure out syntax, though.
namespace MyStuff {
int f();
} // look, ma, no semicolon
namespace m=MyStuff; // namespace alias
void g() { m::f(); } // must be qualified
namespace MyStuff { // extend it; must use original name, not alias.
int ff();
}
using m::f; // import f into current namespace
void h() { f(); } // qualification no longer needed
int MyStuff::f() // define the function in the namespace
{
return ff(); // this doesn't need qualification to use m::ff
}
using namespace m; // drag in the rest of MyStuff too
void k() { ff(); }
Note that MyStuff could have been used in place of m above
except (obviously) in the alias statement. The alias name can't be used
to add to the namespace, so m could not be used there.
Stroustrup hints that it might be a good idea to put everything except main()
into appropriate namespaces. Certainly this would make resolving unintentional
symbol collisions a lot easier at link time.
For more examples, see using.
Sources: