// NamespaceTutorial.cpp
// The primary purpose of this program i
// s to demonstrate the use and value of na
// mespaces.
// Also touched on is using the STL stri
// ng container and typedef.
// In a small program written and mainta
// ined by a small number of people namespa
// ce problems
// are less likely to arise. However in
// large programs maintained by many people
// over long
// periods of time or by anyone developi
// ng reusable libraries of code, namespace
// is a very
// important aspect of programming.
// Okay so what the heck are talking abo
// ut when we say namespace. Well namespace
// parallels
// scope for variable names except inste
// ad of variables we mean function names.
// Variable
// scope allows you reuse a variable nam
// e for different variable even while anot
// her variable
// with that name exists at the same tim
// e in a different scope.
// For example:
// void funcA (int first, int second);
// void funcB (int first, int second);
// void funcC (int first, int second);
// In the above we have three different
// functions each of which will internally
// reference
// a different variables first and secon
// d than any of the others. Otherwise we w
// ould have
// serious problems with the values of t
// hose variables being changed in unpredic
// table and
// uncontrolled ways.
// In a similiar way if Bob writes a lib
// rary and somewhere else in the world Joe
// writes a
// completely different library. Somewhe
// re else Kevin wants to incorporate the h
// ard work
// of these two people into his own code
// and save lots of time, but there is a pr
// oblem. Both
// Bob and Joe have several functions wi
// th the same name: Initialize(), Reinitia
// lize(), Output(),
// Configure(), Transform(), etc. This e
// nds up creating many headaches for Kevin
// who doesn't
// save as much time as he had hoped to.
// Now if the authors of those libraries ha
// d used a
// namespace in defining their library t
// hen Kevin could of indicated which funct
// ion he was
// referring to without fear.
// This principal also works for Classes
// so that within the namespace of your lib
// rary you can
// use Class names that make sense and d
// on't include a bunch goobley-gook. Inste
// ad of using
// a class called MyWSASocketClass, you
// can use a namespace "MyWSA" and a class
// named Socket.
// In the code below the functions are v
// ery simple and while conceptually relate
// d to each
// other, in real code this would not li
// kely be the case. In fact in the below f
// unctions would
// more likely be written as a member fu
// nctions of classes. Please forgive me an
// d look at the
// below code in a structural sense, rat
// her than looking at the names of the nam
// espaces I use.
// The names were changed to protect the
// innocent and have no real bearing on the
// topic other
// than to expedite a sense of what func
// tion is getting called.
// Note that these headers look differen
// t than normal headers
// A normal header would look like: <
// string.h> or
// The use of the these particular heade
// rs indicates that we are using the std n
// amespace
// header for these functions, rather th
// an the older non-namespace headers.
#include
#include
// The word "using" is a directive. It t
// ells the compiler that when referring to
// a something
// named string we want it to look in th
// e namespace std first. It is useful to n
// ote that if
// string is used in a way that is not d
// efined in the std namespace it will look
// elsewhere for it.
using std::string;
// Here we create an alias for the std n
// amespace. I admit that typically you are
// not going to
// create an alias that is even bigger t
// han the original namespace but it illust
// rates this
// ability without overly contriving the
// code. From this point on we can to the s
// td namespace
// using std or standard names. The nice
// thing about this is that library authors
// can use larger
// more descriptive namespace names that
// are very unlikely to cause names clashes
// , and the
// programmer using the library can crea
// te an alias for the namespace within a s
// cope that is not
// going to create name clashes. For exa
// mple a library author could use the foll
// owing namespace:
// namespace felan7476099_hotmail_com_Wi
// ndowsSocket;
// The users of this library within func
// tion that call upon the library create a
// n alias:
// namespace WinSock = felan7476099_hotm
// ail_com_WindowsSocket;
namespace standard = std;
// Here we create a function called Cham
// pion() but we do in a namespace of King.
//
namespace King
{
void Champion()
{
std::cout << "This is the King's Champion" << std::endl;
}
}
// Here we create a function called Cham
// pion() within a namespace of Queen.
namespace Queen
{
void Champion()
{
// this line makes all functions from the std namespace available for use within
// this function only. This allows us to use cout and endl without explicitly
// specifying the std namespace. It is considered poor programming practice to
// do this globally as it defeats the solution namespaces provide. It is possible
// to have several "using namespace" directives in the same function. if you do
// have several "using namespace" directives you can still use the namespace and
// scope resolution operator to indicate which namespace's function you want to
// use in the case of overlapping function names.
using namespace std;
cout << "This is the Queen's Champion" << endl;
}
}
// This Champion() function is declared
// with no namespace and would conflict wit
// h the
// Champion() functions in the King and
// Queen namespaces if those function were
// not in
// the those namespaces.
void Champion()
{
std::cout << "This is a unaffliated Champion" << std::endl;
}
// This function uses the using directiv
// e to indicate which Champion() function
// should be
// used.
void Champions()
{
// this directive says that in this scope for the Champion() function only use the King
// namespace. this directive allows to use the shorter form of Champion() to call the
// same function we would call using King::Champion(). In this function block this is
// trivial as we only call Champion once, however in a large function Champion() could
// get called many many many times and this directive makes it much simplier to call
// the function we want.
using King::Champion;
// Since we are using the King namespace this function is effectively King::Champion()
Champion();
Queen::Champion();
// Since we are in the King namespace calling Champion() would get us King::Champion()
// but we want the Champion() declared in the global namespace, so we use the scope
// resolution operator with no namespace.
::Champion();
}
// The first argument is of the type str
// ing&, which resolves to the same templat
// e class as the
// std::string& thanks to the earlier "u
// sing std::string;" directive we used.
void OutputTestStrings(const string& testa, const std::string& testb)
{
std::cout << testa << std::endl << testb << std::endl << std::endl;
}
int main(int argc, char* argv[])
{
std::string testa = "Test of std::string";
string testb = "Test of string";
standard::cout << "After creating the strings" << standard::endl;
OutputTestStrings(testa, testb);
testa = testb;
std::cout << "After assigning testb to testa" << std::endl;
OutputTestStrings(testa, testb);
std::cout << "Call on the King" << std::endl;
King::Champion();
std::cout << std::endl;
std::cout << "Call on the Queen" << std::endl;
Queen::Champion();
std::cout << std::endl;
std::cout << "Call on a stranger" << std::endl;
Champion();
std::cout << std::endl;
std::cout << "Call on a couple of Champions" << std::endl;
Champions();
std::cout << std::endl;
return 0;
}