While many C++ programmers are familiar with the basic concepts of namespaces, in general, they tend to use namespaces passively. That is, they use namespace members defined by a third-party (such as the Standard Library's classes and functions) but they do not declare their own classes and functions in namespaces. This solution will show you how to declare your classes and functions in a namespace and use them in a program.
A namespace is a scope that contains declarations of classes, functions, constants, templates etc. These are called namespace members. For example:
namespace proj_alpha
{
//the following are members of namespace proj_alpha
class Spy {/*..*/};
void encrypt (char *msg);
const int MAX_SPIES = 8;
}
In the example above, class Spy is implemented in a single source file. Normally, you declare a class in a dedicated header file and define its member functions separately, in a different source file. How do you split a class that is a namespace member into two or more source files?
In the following header file Foo.hpp, I defined a namespace called NS that contains a declaration of class Foo:
//Foo.hpp
namespace NS
{
class Foo
{
public:
void f();
void g();
};
}//close NS
Then, in a separate source file, Foo.cpp, I first #include the header file Foo.hpp add implementations of Foo's member functions f() and g():
//Foo.cpp
#include "Foo.hpp"
void NS::Foo::f()
{ /*..*/ }
void NS::Foo::g()
{ /*..*/ }
To refer to a namespace member, you need to use the member's fully qualified name, which consists of the name of its namespace followed by :: and the member's name.
Thus, the fully qualified name of class Foo is NS::Foo. So that the compiler knows that NS is a namespace name, the header file Foo.hpp must be #included before any reference is made to namespace NS.
Namespaces are extensible. This means that you can declare classes which are members of the same namespace in other .hpp files:
//Bar.hpp
namespace NS //extends NS
{
class Bar
{
public:
void a();
void b();
};
}
Then, in the Bar.cpp file:
#include "Bar.hpp"
void NS::Bar::a()
{/*..*/}
void NS::Bar::b()
{/*..*/}
Now both Foo and Bar are members of namespace NS, although they are declared in separate header files. The compiler and the linker identify these classes as members of the same namespace, although they appear in separate headers. How do you use these classes in an application?
Inside the main.cpp file, you first #include the header files that declare the classes Foo and Bar, and then add appropriate using-declaration:
#include "Bar.hpp"
#include "Foo.hpp"
int main()
{
using NS::Bar; //a using declaration
using NS::Foo; //ditto
Bar b;
Foo f;
f.f();
//...
}
A using-declaration consists of the keyword using followed by a fully qualified name of a namespace member. It enables you to use the non-qualified name of that member in the scope of the using-declaration. In the example above, the non-qualified names Foo and Bar can be used due to the using-declarations at the beginning of main(). Without the using-declarations, the fully-qualified names are needed:
int main()
{
NS::Bar b; //a fully qualified name
NS::Foo f; //ditto
//…
}
There is also a third form of referring to namespace members, namely a using-directive:
#include "Bar.hpp"
#include "Foo.hpp"
int main()
{
using namespace NS; // a using-directive
Bar b;
Foo f;
f.f();
//...
}
A using-directive consists of the keywords 'using namespace' followed by a namespace's name. A using-directive is the least preferable form of accessing namespace members because it injects all the members of its namespace into the current scope, thereby increasing the potential of name conflicts.