Ask the C++ Pro 10-Minute Solutions

Declaring Classes and Member Functions in a Namespace
By Danny Kalev

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.

 
Other 10-Minute Solutions
 How to Change the Mouse Pointer without Flicker
 Setting Full Row Selection in ListView Control
 Automating Type Conversions with stringstream Objects
 Improving Memory Reallocation with Vectors
 How to Use <fstream> Classes for File I/O
 Casting About for Safe Typecasting
 Overloading Operator + the Right Way
 How to Create Persistent Objects
 Making Linked Lists More User-Friendly
 Preventing Glitches in Signal Processing
 Forcing Object Allocation on the Free-store
 Using String-Based Data Validation
 Implementing the 'Resource Acquisition Is Initialization' Idiom
 Simple Locks for Data Files
 Template Specializations
 Exception Handling
 Using Bit Fields in Data Optimization
 Using the Transform() Algorithm to Change a String's Case
 Use RTTI for Dynamic Type Identification
 Choosing the Right swap () Implementation
 Take Charge and Initialize Your Own Data
 Share Data Among Objects Using the Monostate Design Pattern
 String Manipulation Made Easy with std::string Algorithms
 Using typedef to Curb Miscreant Code
 Managing Objects' Construction Order
 Bitwise Operators: Combining Efficiency and Ease of Use
 Use Function Adapters to Extend Generic Algorithms' Usage
 Simplify Callback Dispatching with Enumerated Indexes
 Streamline Your Bulk I/O Operations with Stream Iterators
 Optimize Your Member Layout
 Preserve Code Safety with Conversion Operators
 Modify Your Base Class Interface in Derived Classes
 Tackle Common Programming Tasks Using the New <tuple> Library
 Use Local Classes for Proper Cleanup in Exception-enabled Apps
 Use multimap to Create Associative Containers with Duplicate Keys
 Enforcing Compile-time Constraints
 Facilitate Directory Operations with the <dirent.h> and <dir.h> Libraries
 Spruce Up Your Built-in Arrays
 Target 32- and 64-bit Platforms Together with a Few Simple Datatype Changes
 Restrict Object Allocation to Specific Memory Types
 Use the Pimpl Idiom to Reduce Compilation Time and Enhance Encapsulation
 Automate Resource Management with shared_ptr
 The Quick and Dirty Way to Add
 Pointing to Class Members
 Detecting Keystrokes While Your Application is Busy
 Linked Lists
 Programming the System Tray
 Create a "Universal" DLL
 Convert Path to Long Path Name
 Constructing an Object at a Pre-Determined Memory Position
 Declaring Classes and Member Functions in a Namespace
 Using the auto_ptr Class Template to Facilitate Dynamic Memory Management
 Using the random_shuffle() Algorithm to Randomize a Sequence of Elements
 Defining a Function Object
 Implementing the Singleton Design Pattern
 Declaring Function Pointers and Implementing Callbacks
 Overloading Operator << for a User-Defined Type
 Implementing a Stopwatch Class for Performance Measurements
 Creating and Accessing Environment Variables
 Executing an Object's Member Function in a Separate Thread
 Creating Heterogeneous Containers
 Overriding New and Delete
 Time and Date Manipulation
  Defining Functions with a Variable Argument List
 Optimize Abstract Operations with Function Templates




Sponsored Links


Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map
Jupiterweb networks

internet.comearthweb.comDevx.comClickZ

Search Jupiterweb:

Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents, and JupiterImages

Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers