Namespaces are a relatively new C++ feature just now starting to appear in C++ compilers. We will be describing some aspects of namespaces in subsequent newsletters.
What problem do namespaces solve? Well, suppose that you buy two different general-purpose class libraries from two different vendors, and each library has some features that you'd like to use. You include the headers for each class library:
#include "vendor1.h" #include "vendor2.h"
and then it turns out that the headers have this in them:
// vendor1.h ... various stuff ... class String { ... }; // vendor2.h ... various stuff ... class String { ... };
This usage will trigger a compiler error, because class String is defined twice. In other words, each vendor has included a String class in the class library, leading to a compile-time clash. Even if you could somehow get around this compile-time problem, there is the further problem of link-time clashes, where two libraries contain some identically-named symbols.
The namespace feature gets around this difficulty by means of separate named namespaces:
// vendor1.h ... various stuff ... namespace Vendor1 { class String { ... }; } // vendor2.h ... various stuff ... namespace Vendor2 { class String { ... }; }
There are no longer two classes named String, but instead there are now classes named Vendor1::String and Vendor2::String. In future discussions we will see how namespaces can be used in applications.
In the last issue we discussed one of the problems solved by namespaces, that of conflicting class names. You might be using class libraries from two different vendors, and they both have a String class in them. Using namespaces can help to solve this problem:
namespace Vendor1 { class String { ... }; } namespace Vendor2 { class String { ... }; }
How would you actually use the String classes in these namespaces? There are a couple of common ways of doing so. The first is simply to qualify the class name with the namespace name:
Vendor1::String s1, s2, s3;
This usage declares three strings, each of type Vendor1::String.
Another approach is to use a using directive:
using namespace Vendor1;
Such a directive specifies that the names in the namespace can be used in the scope where the using directive occurs. So, for example, one could say:
using namespace Vendor1; String s1, s2, s3;
and pick up the String class found in the Vendor1 namespace.
What happens if you say:
using namespace Vendor1; using namespace Vendor2;
and both namespaces contain a String class? Will there be a conflict? The answer is "no", unless you try to actually use String. The using directive doesn't add any names to the scope, but simply makes them available. So usage like:
String s1;
would give an error, while:
Vendor1::String s1; Vendor2::String s2;
would still work.
You might have noticed that namespaces have some similarities of notation with nested classes. But namespaces represent a more general way of grouping types and functions. For example, if you have:
class A { void f1(); void f2(); };
then f1() and f2() are member functions of class A, and they operate on objects of class A (via the "this" pointer). In contrast, saying:
namespace A { void f1(); void f2(); }
is a way of grouping functions f1() and f2(), but no objects or class types are involved.
In previous issues we talked about how C++ namespaces can be used to group names together. For example:
namespace A { void f1(); void f2(); } namespace B { void f1(); void f2(); }
The members of the namespace can be accessed by using qualified names, for example:
void g() {A::f1();}
or by saying:
using namespace A; void g() {f1();}
Another interesting aspect of namespaces is that of the unnamed namespace:
namespace { void f1(); int x; }
This is equivalent to:
namespace unique_generated_name { void f1(); int x; } using namespace unique_generated_name;
All unnamed namespaces in a single scope share the same unique name. All global unnamed namespaces in a translation unit are part of the same namespace and are different from similar unnamed namespaces in other translation units. So, for example:
namespace { int x1; namespace { int y1; } } namespace { int x2; namespace { int y2; } }
x1 and x2 are in the same namespace, as are y1 and y2.
Why is this feature useful? It provides an alternative to the keyword "static" for controlling global visibility. "static" has several meanings in C and C++ and can be confusing. If we have:
static int x; static void f() {}
we can replace these lines with:
namespace { int x; void f() {} }
Previously we talked about how namespaces can be used to group names into logical divisions:
namespace Vendor1 { class String { ... }; int x; } namespace Vendor2 { class String { ... }; int x; }
and how those names can be accessed via qualification:
Vendor2::String s;
or a using directive:
using namespace Vendor2; String s;
Another way of accessing names is to employ a using declaration:
using Vendor2::String; String s;
This can be a little confusing. A using directive:
using namespace X;
says that all the names in namespace X are available for use, but none of them are actually declared or introduced. A using declaration, on the other hand, actually introduces a name into the current scope. So saying:
using namespace Vendor2;
makes String and x available for use, but doesn't declare them. Saying:
using Vendor2::String;
actually introduces Vendor2::String into the current scope as a declaration. Saying:
using Vendor1::String; using Vendor2::String;
will trigger a "duplicate declaration" compiler error.
India seo freelance web designer India web development ecommerce website developer India
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100