C++ Namespaces

Namespaces in C++ - Introduction


A namespace is a scope. Namespaces are used to make logical groupings and to avoid potential naming conflicts within C++ applications. Use of namespaces incurs no overhead to application size or performance. To use the contents of a namespace, its contents or those parts of it that are required must be brought into current scope which can be achieved in a number of different ways:


eg. To bring an entire namespace into current scope, use the 'using' keyword, eg:


using namespace std;


This brings the whole of the standard template library (STL) into current scope. This is generally only used in examples; bringing the entire contents of such a namespace into current scope in this fashion defeats the purpose of namespaces. To bring a single namespace member into scope, the using keyword can be used to explicitly refer to that item, eg:


using std::string;


This brings the STL 'string' type into current scope. Alternatively you can simply declare your variable with full namespace syntax within code. eg:


std::string my_string;


This declares my_string as an object of the STL string type.


Using Namespaces In Your Own Applications


Since a namespace is a scope, they can be used to aggregate code with similar intent or functionality. For example, you may have a library of useful utility functions and/or classes. Grouping them together within a subjectively logical namespace and calling it 'utils' would be accomplished thus:


/*
 * The header file
 */
#if !defined HEADER_INCLUDE_GUARD 
#define HEADER_INCLUDE_GUARD 


namespace Utils
{
  class SomethingUseful
  {
    public:
      SomethingUseful(void);
      ~SomethingUseful();
  };
} /* end Utils namespace */
#endif 


/*
 * The source file
 */
#include "the header file" 
namespace Utils
{
  SomethingUseful::SomethingUseful(void)
  {
    cout <<"Doing SomethingUseful";
  }


  SomethingUseful::~SomethingUseful(void)
  {
    cout <<"Doing ~SomethingUseful";
  }
} //end Utils namespace


/*
 * Alternative syntax for the source file :
 */


#include "the header file" 
Utils::SomethingUseful::SomethingUseful()
{
  cout <<"Doing SomethingUseful";
}
Utils::SomethingUseful::~SomethingUseful(void)
{
  cout <<"Doing ~SomethingUseful";
}






The second source file syntax clearly shows the scoping nature of namespaces while the first example involves less typing. Also some IDE's (eg. Visual C++ 6) class viewers cannot cope with the second syntax.


Note that any namespace is open: you can have multiple files wrapped within the same namespace beyond single header/source file pairs as demonstrated above. This permits addition to the namespace at a later date, if required. The syntax remains unchanged; you can either wrap the contents of the new file(s) within:


namespace name_of_namespace {...}


where the ellipsis (...) represents the new member(s) added to the namespace.


Or, for source files, you may prefer to use the alternative syntax of:


name_of_namespace::member_name


where name_of_namespace is the namespace name you are adding to and member_name is the name of some member class, function or variable within that namespace.


Nested Namespaces


Namespaces can be nested:


namespace outer
{
  namespace inner
  {
  }
}






Namespace Alias


It is possible to use an alias to represent the name of another namespace. For example, in the nested namespace above, any member of 'inner' could be accessed by:


outer::inner::member name


Where 'member name' is the name of some member function, variable or class. Alternatively, using an alias (eg 'aoi' for 'alias-outer-inner'):


namespace aoi = outer::inner;


and a member of 'inner' can now be accessed with:


aoi::member name


Unnamed Namespaces


For simplicity and the convenience of wrapping a set of declarations/definitions to guard against potential name clashes it is possible to omit a name for the namespace, eg:


namespace 
{
  int    a;
  char *b;
}






The unnamed namespace has an implicit 'using' directive so there is no problem accessing its members ie. they can be accessed as if they actually have global scope but in reality they have their names mangled by the compiler to ensure naming conflicts do not occur.


Using Namespaces
One of C++'s less heralded additions is addition of namespaces, which can be used to structure a program into "logical units". A namespace functions in the same way that a company division might function -- inside a namespace you include all functions appropriate for fulfilling a certain goal. For instance, if you had a program that connected to the Internet, you might have a namespace to handle all connection functions:


namespace net_connect
{
  int make_connection();
  int test_connection();
  //so forth...
}


You can then refer to functions that are part of a namespace by prefixing the function with the namespace name followed by the scope operator -- ::. For instance,


net_connect::make_connection()


By enabling this program structure, C++ makes it easier for you to divide up a program into groups that each perform their own separate functions, in the same way that classes or structs simplify object oriented design. But namespaces, unlike classes, do not require instantiation; you do not need an object to use a specific namespace. You only need to prefix the function you wish to call with namespace_name:: -- similar to how you would call a static member function of a class.


Another convenience of namespaces is that they allow you to use the same function name, when it makes sense to do so, to perform multiple different actions. For instance, if you were implementing a low-level IO routine and a higher level IO routine that uses that lower level IO, you might want to have the option of having two different functions named "input" -- one that handles low-level keyboard IO and one that handles converting that IO into the proper data type and setting its value to a variable of the proper type.


So far, when we've wanted to use a namespace, we've had to refer to the functions within the namespace by including the namespace identifier followed by the scope operator. You can, however, introduce an entire namespace into a section of code by using the syntax


using namespace_name;


Doing so will allow the programmer to call functions from within the namespace without having to specify the namespace of the function while in the current scope. (Generally, until the next closing bracket, or the entire file, if you aren't inside a block of code.) This convenience can be abused by using a namespace globally, which defeats some of the purpose of using a namespace. A common example of this usage is


using namespace std; 


which grants access to the std namespace that includes C++ I/O objects cout and cin.


Finally, you can introduce only specific members of a namespace using the syntax


using namespace_name::thing;


One trick with namespaces is to use an unnamed namespace to avoid naming conflicts. To do so, simply declare a namespace with the normal syntax, but leave off the identifier; when this is done, you will have


namespace
{
  //functions
}


and within the namespace you are assured that no global names will conflict because each namespace's function names take precedence over outside function names.


Now, you might ask, how can you actually use anything in that namespace? When your program is compiled, the "anonymous" namespace you have created will be accessible within the file you created it in. In effect, it's as though an additional "using" clause was included implicitly. This effectively limits the scope of anything in the namespace to the file level (so you can't call the functions in that namespace from another other file). This is comparable to the effect of the static keyword.


Renaming namespaces
Finally, if you just don't feel like typing the entire name of namespace, but you're trying to keep to a good style and not use the using keyword, you can rename a namespace to reduce the typing:


namespace <new> = <old>


Related articles

The many uses of the static keyword in C and C++


From: www.Cprogramming.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值