C++ namespace instance resolution

  • 2020-04-02 02:36:58
  • OfStack

Namespace is a very important concept in C++. This paper makes an in-depth analysis of it in the form of an example. The specific contents are as follows:

In general, the purpose of namespaces (namespaces) in C++ is to prevent name collisions. Each namespace is a scope, and in addition to all namespaces, there is a global namespace, which is implicitly declared as having no name. In the namespace mechanism, the original global variable is in the global namespace (can be expressed as ::member).

Define a namespace

1. Each namespace is a scope

Like other scopes, each name in a namespace must represent a unique entity, and members with the same name can exist in different namespaces.

2. Namespaces can be discontinuous

Namespaces can be defined in several different parts:


namespace nsp { 
   
}  //There is no semicolon after the namespace scope

If there is no previous namespace definition named NSP, the code above creates a new namespace. Otherwise, the code above opens the existing namespace and adds some new members.

3. Namespaces can be nested

A nested namespace is a namespace defined in another namespace. A nested namespace is a nested scope, and the name of the inner namespace declaration hides the member of the outer namespace declaration with the same name:


int x = 20; 
namespace outer { 
  int x = 10; 
  namespace inner { 
    int z = x; 
  } 
} 
 
int main() 
{ 
  std::cout << outer::inner::z; //The output of 10
  return 0; 
} 

Note that we generally don't put the #include header file inside the namespace.

4. Unnamed namespaces

Unnamed namespaces (unnamed namespace) refers to the namespace keyword followed braces after a series of statements enclosed. Variables defined in an unnamed namespace have a static life cycle: they are created before they are first used and are not destroyed until the end of the program. Before standard C++ introduced the concept of namespaces, programs needed to declare the name static to be valid for the entire file, but the practice of static declarations in files has been abolished by the C++ standard, which USES unnamed namespaces instead.

An unnamed namespace can be discontinuous within a given file, but cannot span multiple files. That is, an unnamed namespace is only valid within a particular file and does not span many different files. Also, because an unnamed namespace has no name, the scope of the name defined is the same as the scope of the namespace:


int i;  //Global declaration of I
namespace { 
  int i; 
} 
i = 10; //Error, ambiguity


namespace local { 
  namespace { 
    int i; 
  } 
} 
local::i = 42; //correct

Use namespaces

A reference to a member in a namespace requires the namespace's scope operator (::). However, using namespace members like namespace_name::member_name is cumbersome, and we need to use some other, simpler methods.

1. Alias of namespace

Some namespaces have long names or multiple levels of nested namespaces, so we can give them a shorter synonym, or alias:


namespace cln = cpluslus_learning_namespace; 
namespace Qlib = outer::inner::QueryLib; 

2. Using declaration

A using declaration statement introduces only one member of the namespace at a time:


using  Namespace name ::[ Namespace name :: ... ] Member name ;  //For example using OLib: : List;

Using indicator

The difference between a using directive and a using declaration is that we cannot control which names are visible, because the using directive makes all names visible in a particular namespace:


using namespace std;  //Introduce the namespace STD

The main purpose of using namespaces is to prevent name collisions, and the problem of name collisions is reintroduced if you arbitrarily use using to indicate all names injected into a namespace. In addition, The using declaration and the using indication differ in scope The using declaration introduces a member into the current namespace scope. Using indicates that all members are brought into the current and previous namespace scope:


namespace nsp {  //The namespace
  int i=16, j=15; 
} 
 
int j = 0;  //The global variable
 
int main() 
{ 
  using namespace nsp;  //If j is used, there is a conflict between ::j and NSP ::j
  std::cout << j; 
  return 0; 
}

If the using namespace NSP; Change to using statement using NSP ::j; It will print 15 correctly.


Related articles: