Tuesday, May 29, 2012

C++ Namespaces

Back in the day when C was the only kid in town, there was a default namespace. This global default namespace is what I would argue was the primitive Java package. Packages are a way of dividing up code; not only for visual organization but functional organization. There is no way to know that com.packageOne.myClass's toString() method could be different from com.packageTwo.myClass's toString() method without that com.whatever coming before it.

With the advent of C++, the standard namespace is std, and many C++ programmers use the line using namespace std to declare the standard namespace as std. std contains functions such as cout and others. The developer, however, can create a namespace called myStd and define a completely DIFFERENT cout function and have no clashes.

How do we do this wonderful piece of programming? Below is an example a header file containing a bunch of defined namespaces:

 1 #ifndef MILITARY_RANK_H
 2 #define MILITARY_RANK_H
 3 
 4 namespace Captain {
 5  char * getMilitaryRank(){
 6   return "Captain";
 7  }
 8 }
 9 
10 namespace Commander {
11  char * getMilitaryRank(){
12   return "Commander";
13  }
14 }
15 
16 namespace LieutenantCommander {
17  char * getMilitaryRank(){
18   return "Lieutenant Commander";
19  }
20 }
21 
22 namespace Lieutenant {
23  char * getMilitaryRank(){
24   return "Lieutenant";
25  }
26 }
27 
28 #endif


The above code defines four different namespaces; each namespace contains the same function definition, but the returned char * for each function is different. It is this simple to make a namespace, by the way. Below, I present my main implementation:

 1 #include <iostream>
 2 #include "MilitaryRank.h"
 3 
 4 namespace Captain {
 5  char * getOrders(){
 6   return "Number one, stand down red alert.";
 7  }
 8 }
 9 
10 int main(){
11  std::cout << Captain::getMilitaryRank() << std::endl;
12  std::cout << Captain::getOrders() << std::endl;
13  std::cout << Commander::getMilitaryRank() << std::endl;
14  std::cout << LieutenantCommander::getMilitaryRank() << std::endl;
15  std::cout << Lieutenant::getMilitaryRank() << std::endl;
16  char something;
17  std::cin >> something;
18 }


Notice that I define the same Captain namespace again at the top, and define a function in it. C++ is smart enough to recognize that both of these functions are in the same namespace, Captain. This is powerful, because it lets you create multiple .cpp or .h files that share the same namespace (like classes that share the same package in Java). The namespaces are referenced directly, and the scope resolution operation (::) is used to get reference to those methods. Notice that I omit the using namespace std and opted to call its functions directly. If I wanted to, I could have used using nsmespace Captain and for the Captain::function calls, I could have just called them without using the scope resolution operator

Lastly, here is the output:


Namespaces are something that C++ developers should take advantage of. They can  make large projects much cleaner. Note, however, that you should never, ever, ever have a program contain std::cin, because buffer overflow is one of the easiest way for hackers to exploit your program.

No comments:

Post a Comment