30 Namespace in C++

Jyotika Doshi

Introduction

 

In C++, identifiers may have either local or global scope. C++ allows unique names in specific scope. When C++ application uses libraries from different vendors or when application is developed using multiple source files written by various programmers, there are chances of having identifiers with same name in global scope namespace. This introduces a problem of name conflict. Namespace helps to prevent such name conflict by allowing identifiers to be grouped in a user-defined namespace.

 

What is namespace?

 

Namespace is a declarative region providing a scope to the identifiers contained in it. The identifiers are named entities, such as variable, function, class, object, typename, struct, enum or other compound types. Identifiers should have unique names in a namespace.

 

Why namespace?

 

Before understanding the need of namespace, let us recall the knowledge about global and local scope of variables. Namespace is sometimes referred to as scope also.

 

Named entities, such as variables, functions, class need to be declared before being used in C++. Depending upon the location of their declaration in a program, entities are having their scope or visibility.

 

1.1. Local namespace

 

An entity declared within a block has block scope. Block may be introduced using statements in a pair of curly braces. Some examples of blocks are functions, loops, conditions. Parameters of a function and entities declared within a block are local to the block. Such entities are visible only within the specific block in which they are declared, but not outside it. Their storage class is auto; i.e. they are created when the block is executed and their life is till the end of block. Variables with block scope are known as local variables. They are not initialized with any default value.

 

Local variables are in local namespace.

 

1.2. Global namespace

 

An entity declared outside any block has global scope, meaning that its name is valid anywhere in the code. Storage for global entities is static. Their life is for the entire duration of the program. Variables with global scope are known as global variables. By default, variables with static storage are initialized to zeroes, so global variables have zero as their initial value.

 

Global variables are in global namespace.

 

1.3. Unique name in namespace

 

In each scope, may be block (local) or global, a name can represent only one entity. Thus, there cannot be two variables with the same name in the same scope.

 

int function1 ()

{

int x;

 

x = 0;

 

double x; // wrong: name already used in this scope x = 0.0;

}

 

Blocks may be nested. The visibility of an entity with block scope extends until the end of the block, including inner blocks. An inner block, being a different block, can re-utilize a name existing in an outer block scope to refer to a different entity. In such case, the name will refer to a different entity within the inner block, hiding the entity with the same name in outer block scope.

 

In the following example, note that variable y of outer block has a scope in nested block also. There is no variable named y in inner block. But variable named x occurs in outer block as well as in inner block. Re-utilizing variable name x in inner block hides variable x of outer block. See global variable named x declared outside block. To refer it within block, it requires using scope resolution operator.

 

cout << “x: ” << x << ‘\n’;

cout << “y: ” << y << ‘\n’;

}

cout << “outer block:\n”;

cout << “x: ” << x << ‘\n’;

cout << “y: ” << y << ‘\n’;

cout << “global variable x: ” << ::x << ‘\n’;

return 0;

}

1.4. Need of namespace

 

As explained, only one entity can exist with a particular name in a particular scope or namespace in C++.

 

For local variables in block scope, there is hardly a chance for entities with same name; because blocks tend to be relatively short and names have particular purposes within them. But, for global scope, chances are very high for having multiple entities with same name as explained in following scenario.

 

Real applications are usually very large and divided into multiple modules or tasks. These modules are mostly developed by more than one developer in an independent manner. It is possible that different developers used same variable name or class name for different purposes in their programs. To produce the final application, these separate source files are compiled and linked. Application will not be created successfully due to conflict in names. Error will occur considering re-declaration of a variable.

 

For example, consider an event management application consisting of many program files. Assume one file having variable ‘length’ referring to number of days of an event. In another file, variable ‘length’ is used to store number of characters used in the string representing event name. While linking these two files, problem will arise due to name clash in variable ‘length’.

 

Many times, application may include libraries developed by different vendors. Hence, it is possible to have entities with same name in different libraries.

 

For example, assume library1 containing class Angle in degree and library2 containing class Angle in radian. When these two libraries are included in a program, occurrence of repeated entity name Angle will create a conflict.

 

C++ do not allow two entities with the same name in the same scope. Entities declared in separate files or libraries share global namespace. Hence, multiple definitions of names or name clashes may be encountered while linking the separate modules.

 

To solve this problem, some workarounds may be like

  • vendors or developers should cooperate with some strategy to have unique names
  • use dummy classes or structs to group names

C++ provides a better solution with namespace mechanism to overcome the problem of name clashes in the global scope.

 

The namespace mechanism allows global scope to be partitioned into number of sub-scopes, each sub-scope having its own name. In essence, a namespace defines a user-defined scope. User can create namespace to hold logical grouping of unique identifiers. An identifier defined in a namespace is associated only with that namespace. Thus, identifiers of one namespace do not conflict with identifiers in another user-defined namespace or global namespace.

 

Thus, namespace provides a method for preventing name conflicts in large projects.

 

Using namespace, one can define the context in which names are defined.

 

Namespaces are used to organize code into logical groups and prevent name collisions that can occur especially when the code base includes multiple libraries.

 

Using namespace   Using namespace involves:

  • Creating namespace with unique identifiers as its members or elements
  • Accessing elements or members of namespace

1.5. Creating Namespace

 

The syntax to declare a namespaces is: namespace namespace_name

 

{ //namespace body

  • // identifier declarations

}

  • A namespace definition begins with the keyword namespace followed by the user-defined name of namespace and its body in a pair of curly brackets.
  • Body part contains identifiers as its members having unique name. Identifiers may be variables, constants, functions, class, objects of class etc.
  • Namespace definition doesn’t terminate with a semicolon.
  • Function or class can be declared in namespace and defined outside namespace.

 

Note that a namespace definition must appear either at file scope, or immediately within another namespace definition. It cannot be defined at block scope, so cannot be defined in main(). Following example illustrates declaring variable, function, class and object in a namespace named myNamespace.

 

namespace myNamespace

{

int num = 5; // variable declaration

 

int isLeap(int y) // non-member function declaration

{

if ( (y%400 ==0) || (y%4==0 && y%100 !=0) ) return 1; else return 0;

}

class Point     // class declaration

{

float x,y;

public:

Point() {x = y = 0;}

Point(float p1, float p2) {x=p1; y=p2;}

void show() {cout << ‘(‘ << x << ‘,’ << y << ‘)’;} }; // end class

Point pt; // object declaration

 

} // end myNamespace

 

Function and class can be declared inside the namespace and defined outside it using scope resolution operator as follows:

 

namespace myNamespace

{

int num = 5; // variable declaration

int isLeap(int y); // non-member function declaration

class Point;     // class declaration

//Point pt; // object declaration, error:’pt’ uses undefined class

‘myNamespace::Point’

} // end myNamespace

 

//defining function and class outside namespace using scope resolution operator int myNamespace::isLeap(int y) // non-member function definition

{

if ( (y%400 ==0) || (y%4==0 && y%100 !=0) ) return 1; else return 0;

}

class myNamespace::Point       // class definition outside namespace

 

{

float x,y;

public:

Point() {x = y = 0;}

 

Point(float p1, float p2) {x=p1; y=p2;}

 

void show() {cout << ‘(‘ << x << ‘,’ << y << ‘)’;} }; // end class

 

It is possible to define class in namespace with its methods defined outside namespace as follows:

namespace myNamespace

{

int num = 5; // variable declaration

int isLeap(int y); // non-member function declaration class Point // class definition

{

float x,y;

public:

Point() {x = y = 0;}

Point(float p1, float p2) {x=p1; y=p2;}

void show(); // prototype declaration

}; // end class

 

} // end myNamespace

 

// function defined outside namespace

int myNamespace::isLeap(int y) // non-member function definition

 

{

if ( (y%400 ==0) || (y%4==0 && y%100 !=0) ) return 1; else return 0;

}

  • // class method show() defined outside class, outside namespace void myNamespace::Point::show() // definition

{cout << ‘(‘ << x << ‘,’ << y << ‘)’;}

 

 

1.6. Accessing elements of namespace

 

All identifiers within the scope are directly accessible without qualification. But outside the namespace scope, identifiers can be accessed by using the fully qualified name, or by using Declaration for a single identifier, or by using Directive for all the identifiers in the namespace. Thus there are three ways that code outside namespace can access their elements.

  • Using fully qualified name with scope resolution operator ::
  • Importing entire namespace using directive
  • Importing single element at a time from namespace using declaration

1.6.1. Accessing namespace elements using scope resolution operator

 

Any name (identifier) declared in a namespace can be explicitly referred using the namespace’s name and the scope resolution operator with the identifier. This type of accessing name is also referred to as fully qualified name. Following example defines identifier named ‘num’ in global namespace and in user-defined namespace. Identifier of user-defined namespace is referred using fully qualified name.

 

 

#include <iostream>

using namespace std;

int num=50; // global var

namespace myNamespace

 

{

int num = 5; // variable declaration

int isLeap(int y) // non-member function definition

{

if ( (y%400 ==0) || (y%4==0 && y%100 !=0) ) return 1; else return 0;

 

}

class Point       // class definition

{

float x,y;

 

public:

Point() {x = y = 0;}

Point(float p1, float p2) {x=p1; y=p2;}

 

void show() {cout << ‘(‘ << x << ‘,’ << y << ‘)’;} }; // end class

Point pt; // object declaration

} // end myNamespace

 

int main()

{

cout << “Global scope num: ” << num << endl;

cout << “myNamespace scope num: ” << myNamespace::num << endl;

cout << “Enter year:”;

cin >> num;

if (myNamespace::isLeap(num)) cout << num << ” is a leap year” << endl;

else cout << num << ” is not a leap year” << endl;

myNamespace::pt.show();

myNamespace::Point pt1(3.5, 4.5);

pt1.show();

return 0;

}

 

Output:

 

Global scope num: 50

myNamespace scope num: 5

Enter year:1900

1900 is not a leap year

 

(0,0)(3.5,4.5)

 

Refer following example having three variables with same name; each in global, local and user-defined namespace scope.

  • // namescope element access with qualified name
  • // 3 variables with same name but in different scopes #include <iostream>

using namespace std;

 

int num=50; // global variable

namespace myFirstNamespace

 

{  int num = 5; }

 

int main()

{

int num = 70; // block scope (local variable) cout << “Global scope num: ” << ::num << endl; cout << “Block scope num: ” << num << endl;

cout << “myFirstNamespace scope num: ” << myFirstNamespace::num << endl; return 0;

}

 

Output:

Global scope num: 50

Block scope num: 70

myFirstNamespace scope num: 5

Identifiers will be looked up first in local namespace. So, global declarations with the same name can be accessed using scope resolution (::) .

 

1.6.2. Importing namespace elements with keyword ‘using’

 

The using keyword can be used to import entire or part of namespace into current declarative region.

Names introduced into a namespace scope with ‘using’ can be used with or without qualification from other scopes.

When we use using directive, we import all the names in the namespace. But with using declaration, we import one specific name at a time.

Namespace can be introduced to another named namespace or to a local block scope or file scope in a program depending upon where ‘using’ is introduced.

Names introduced with ‘using’ keyword obey normal scope rules. The name is visible from the point of the ‘using’ to the end of the scope in which the directive/declaration is found.

Entities with the same name defined in an outer scope are hidden.

 

1.7. Examples to understand use of directive and declaration at various scopes

 

Syntax for importing entire namespace with ‘using directive’:

using namespace <namespace_name> Syntax for importing single element from namespace with ‘using declaration’:

using <namespace_name::element_name>

Note that keyword ‘namespace’ is not used in ‘using declaration’.

 

1.7.1. Using Directive at block (local) scope

 

Following example shows importing all names from namespace using directive at block scope. Within block, namespace identifiers are referred without qualification.

  • // importing entire namespace using directive
  • // importing namespace at block scope #include <iostream>

using namespace std; namespace first

 

{ int x = 5; int y = 10;} namespace second

{ double x = 3.1416; int y = 20; }

int main()

{

{ // block1

using namespace first; // import all identifiers of first in current block’s scope cout << x << ‘, ‘ << y << ‘\n’;

}

{// block2

using namespace second; // import all identifiers of second in current block’s scope

cout << x << ‘, ‘ << y << ‘\n’;

}

return 0;

 

}

 

Output:

 

5, 10

3.1416, 20

 

Removing blocks from ‘main’ in above code will raise ambiguity in names x and y when elements of namespace second are accessed. Note that variables x and y are not redefined here, they are just imported to be in current scope. So, error is not flagged at the time of importing with using directive.

 

int main()

 

{

 

using namespace first; // import all identifiers of first in current block’s scope cout << x << ‘,’ << y << ‘\n’;

using namespace second; // import all identifiers of second in current block’s scope

cout << x << ‘,’ << y << ‘\n’; // ambiguous x and y

}

 

To get rid of error due to ambiguity in names, use fully qualified name like second::x and second::y. Note that it is always safer to use fully qualified name.

Note that identifiers of local namespace hide identical names of namespace even when directive is used. Try defining int x = 555 in main() and see the result.

1.7.2. Using Directive at file scope (global within single source file)

 

When ‘using namespace’ or ‘using’ is used outside any block like global variables, its elements have file scope. It means that such identifiers are visible only in this specific file; they are not available in other files. This is how it differs from normal global scope. Variables defined in global namespace can be availed in other files by declaring them as ‘extern’. Identifiers of namespace cannot be declared as ‘extern’. If needed in another file, they need to be imported with ‘using’ keyword.

 

  • // importing entire namespace using directive
  • // importing namespace at file (global in file) scope #include <iostream>

using namespace std;

 

namespace first

 

{ int x = 5; int y = 10;} namespace second

{ double x = 3.1416; int y = 20; }

 

using namespace first; // import all identifiers of namespace first here, at file scope

 

int main ()

{

cout << “from first namespace: ” << x << “, ” << y << ‘\n’;

 

cout << “from second namespace: ” << second::x << “, ” << second::y << ‘\n’; return 0;

}

 

Output:

 

from first namespace: 5, 10

from second namespace: 3.1416, 20

 

When identifiers in global namespace collide with identifiers in namespace scope, it results in compile time error. Adding int x; before main() in above code will give an error due to ambiguity at the point where x is used. Error is not flagged at the point of defining x with the same name or at the time of importing namespace.In this example, what will happen if both namespaces are imported at global or file scope here? Will it create name conflict problem?

 

1.7.3. Using Directive at another namespace scope

  • // importing entire namespace with using directive into another namespace #include <iostream>

using namespace std;

namespace second

{ double x = 3.1416; int y = 20; } namespace third

{ using namespace second; // import namespace second in namespace third double xx = 7.14; int yy = 50; }

using namespace third; // import namespace third here, global scope

int main ()

{

cout << “from third namespace: ” << x << “, ” << y

  • << “, ” << xx << “, ” << yy << ‘\n’; return 0;

}

 

Output:

 

from third namespace: 3.1416, 20, 7.14, 50

 

1.7.4. Using declaration at various scopes

 

‘Using declaration’ enables to import only one element of namespace at a time in current scope where it is used. Refer following example where a single element y of namespace first is imported at global scope. As seen in previous examples, it can be imported at block scope or at another namespace scope also.

  • // importing single element at a time from namespace using declaration #include <iostream>

using namespace std;

 

namespace first

{ int x = 5; int y = 10;}

using first::y; // using declarative at global scope

int x; // global variable

 

int main ()

{

int x=50; // local variable

  • // global ::x; local x; first::x and y from namespace first cout << ::x << “, ” << x << “, ” << first::x << “, ” << y << ‘\n’; return 0;

}

 

Output:

 

0, 50, 5, 10

 

 

In above example, importing first::x at global scope or block scope of main() will raise conflict as there is variable x with same name defined in the same scope. At global scope, it conflicts with global x; and at local scope, it conflicts with local x. In such cases, one may use ‘using declaration’ to import single element of namespace instead of importing all elements of namespace. Here, only element y of namespace first is imported in global scope.

 

1.7.5. Overriding name when same name is imported from different namespaces in same scope

  • // importing entire namespace using directive and single element using declaration
  • // overriding name when same name is imported from namespace scope

#include <iostream>

 

using namespace std;

namespace first { int x = 5; int y = 10;}

namespace second { double x = 3.1416; int y = 20; }

int main ()

{

using namespace first; // x, y of first in block scope of main()

using second::x; // identifier x of namespace second overrides x of namespace first cout << x << “, ” << y << ‘\n’; // refers to second::x, first::y

cout << first::x << ‘\n’; // x of first accessible using fully qualified name return 0;

}

 

Output:

 

3.1416, 10

5

Here, variable x of second namespace is imported after variables x and y of first namespace at block scope. Name imported later overrides already imported names. As seen in all above examples, using and using namespace have validity only in the same block in which they are stated or in the entire source code file if they are used directly in the global scope.

 

Namespace std

 

All the entities (variables, types, constants, and functions) of the standard C++ library are declared within the std namespace. Most examples used here include following line at file scope:

 

using namespace std;

 

This introduces direct visibility of all the names of the std namespace into the code. So, objects like cout and cin defined in std namespace are accessible without scope resolution operator.  Without use of ‘using namespace std’, one will have to use std::cout and std::cin.

 

For example, instead of

cout << “Hello world”;

it requires writing

std::cout << “Hello world”;

 

Including line ‘using namespace std;’ at file scope facilitate comprehension and shorten the length of the code. Many programmers prefer to qualify each of the elements of the standard library used in their programs.

 

Whether the elements in the std namespace are introduced with using declarations or are fully qualified on every use, it does not change the behaviour or efficiency of the resulting program in any way. It is mostly a matter of style preference. Although for projects with mixing libraries, explicit qualification tends to be preferred.

 

Anonymous Namespace

 

It is possible to create a namespace without giving any name. Such namespaces are called anonymous or unnamed namespaces. Unnamed namespace can contain everything like named namespace. But, as it is not given any name, its elements cannot be accessed using qualified name or cannot be imported with ‘using’ keyword. Elements of unnamed namespace are available at file scope and can be accessed just like normal global variables within the file only.

Refer following example.

// Unnamed namespace

#include <iostream>

using namespace std;

namespace // anonymous, not given any name

{ int x; int y; }

int main ()

{

cout << “Enter two integres:”;

cin >> x >> y;

cout << x << “, ” << y << ‘\n’;

return 0;

}

Output:

Enter two integres:5 10

5, 10

 

 

Even though variables x and y of anonymous namespace are accessed like normal global variables, they are not available in other files. They cannot be declared as ‘extern’ in other files.Unnamed namespace is unique within a file, i.e. there cannot be more than one unnamed namespace in a file. When unnamed space is defined again, it is considered as an extension to an existing unnamed space.

  • // redefining unnamed space extends existing unnamed space #include <iostream>

using namespace std;

 

namespace // anonymous, not given any name

{ int x; int y; }

namespace // anonymous, extended

{ int xx=10; int yy=20; } int main ()

{

cout << “Enter two integres:”; cin >> x >> y;

cout << x << “, ” << y << ‘\n’; cout << xx << “, ” << yy << ‘\n’;

return 0;

 

}

 

Output:

Enter two integres:50 70

 

50, 70

10, 20

What if a variable with the same name occurs at local and global scope? Refer following example.

  • // variables with same name in global, local and anonymous namespace scope #include <iostream>

using namespace std;

 

namespace // anonymous, not given any name

{ int x=5; int y=25; }

namespace // anonymous, not given any name

{ int xx=10; int yy=20; } int x=55; //global

int main ()

{

int x=75; // local

cout << ::x << “, ” << x << “, ” << y << ‘\n’;

cout << xx << “, ” << yy << ‘\n’;

return 0;

}

 

Output:

55, 75, 25

 

10, 20

 

It can be observed that a variable in global scope is still available using scope resolution operator, but local variable hides the same name from anonymous namespace.

 

Nested Namespace

 

A namespace definition can be nested within another namespace definition. Every namespace definition must appear either at file scope or immediately within another namespace definition.  Namespace can be nested up to any level.Elements of nested namespace can be accessed using qualified name and can also be imported with ‘using’.

 

See following example.

 

#include <iostream>

using namespace std;

namespace namespaceOuter

{

float num1 = 10.5;

namespace namespaceInner1 //nested

{ float num1 = 25.25; float num2 = 30.75; }

}

int main ()

 

{

//Accessing elements of nested namespace

//With qualified name using scope resolution operator cout << “outer num1:” << namespaceOuter::num1 << endl;

cout << “Inner num1:” << namespaceOuter::namespaceInner1::num1 << endl; cout << “Inner num2:” << namespaceOuter::namespaceInner1::num2 << endl;

//With ‘using’ keyword:

using namespace namespaceOuter::namespaceInner1;

cout << ” with using, inner num1 and num2…” << num1 << ” ” << num2 << endl;

}

 

Output:

 

outer num1:10.5

Inner num1:25.25

Inner num2:30.75

with using, inner num1 and num2…25.25 30.75

Namespace Aliasing

 

Namespace aliasing allow the programmer to define an alternate name for a namespace.It is commonly used as a convenient shortcut for long or deeply-nested namespaces. Existing namespace can be aliased with new name, with the following syntax: namespace new_name = current_name; Aliasing helps to reduce the length of long fully qualified names: namespace ns1 = namespaceOuter::namespaceInner1; cout << ns1::num1 << ns1::num2;

 

Aliasing also helps to get rid of changes in program code in case name of namespace is changed. Here, the purpose is somewhat similar to using #define. For example, if name of namespace namespaceInner1 is changed to namespaceLevel1, merely change in alias name helps in getting rid of changes wherever its elements are referred in a program.

 

namespace ns1 = namespaceOuter::namespaceLevel1; // change in namespace name

 

cout << ns1::num1 << ns1::num2; // unaffected by name change due to alias

//Namespace aliasing

#include <iostream>

using namespace std;

namespace namespaceOuter

 

{

float num1 = 10.5;

namespace namespaceInner1 //nested

{ float num1 = 25.25; float num2 = 30.75; }

}

 

int main ()

{

namespace ns1 = namespaceOuter::namespaceInner1; // creating alias // using alias ns1 – ns1::num1, ns1::num2

cout << “Using alias – inner num1 and num2: ” << ns1::num1 << ” ” <<

ns1::num2 << endl;

}

 

Output:

 

Using alias – inner num1 and num2: 25.25 30.75

 

Extending Namespace

 

A namespace definition can be extended within the same file or over multiple files. This enables to split the namespace by declaring its elements in several parts as per need. So it can be referred to as discontinuous namespace also.

 

Extending namespace is useful when a large application is developed by more than one programmer. Programmers may define identifiers as per their individual need in the namespace and can be added in program code with other identifiers in the same namespace.

 

Syntax to extend namespace is same as creating namespace. Defining namespace for the first time creates new namespace. Redefining existing namespace simply extends it adding new elements.

 

Note: The namespace is not overwritten or overridden. It is either created or extended.

 

Consider following examples:

  • // extending named namespace #include <iostream>

using namespace std; namespace myNamespace { float num1 = 10.5; } namespace myNamespace // extended myNamespace { float num2 = 30.75; }

 

using namespace myNamespace;

int main ()

{

cout << “myNamespace num1 and num2…” << num1 << ” ” << num2 << endl; return 0;

}

Output:

 

myNamespace num1 and num2…10.5 30.75

 

Consider following example of namespace extended after importing its elements. Here, namespace have two function members f(int) and f(char). The namespace is extended after the using-declaration of elements from existing namespace with member f(int). The namespace is extended but additional declarations f(char) with same name do not become visible through the using-declaration (in contrast with using-directive).

  • // extending named namespace after using declaration #include <iostream>

using namespace std;

 

namespace ns

 

{ void f(int x) {cout << x << endl; } } using ns::f; // f now refers to ns::f(int)

 

namespace ns // namespace extension

{ void f (char c) {cout << c << endl; } } // added f(char) in namespace ns

 

int main ()

 

{

 

f(‘a’); // calls f(int), even though f(char) exists as f(char) not in scope ns::f(‘a’); // explicit qualification

using ns::f; // again using, now f is a synonym for both ns::f(int) and ns::f(char)

f(‘a’); // calls f(char)

f(65); // calls f(int)

return 0;

}

 

Output:

 

97

a

a

65

 

 

Observe following from the output:

  • first call f(‘a’) calls f(int) as f(char) is not visible here and char can be implicitly converted to int.
  • In next line, call ns::f(‘a’) with explicit qualification called f(char). It means f(char) is there in namespace, but it is yet not imported into current scope.With declaration ‘using ns::f’, now
  • f(char) is also in scope. So next calls f(‘a’) and f(65) calls f(char) and f(int) respectively.

Modify above code to replace line ‘using ns::f’ with line ‘using namespace ns’ before extending namespace. See the effect. Now the output shows that it calls f(char), f(char), f(char) and f(int) displaying a, a, a and 65.

 

The point is: If the namespace is extended after the using-declaration of elements from existing namespace, the namespace is extended but additional declarations do not become visible through the using-declaration (in contrast with using-directive).

 

Do namespace introduce any overhead?

 

Namespace does not introduce any overhead at runtime as namespaces are resolved at compile time. All fully qualified name and using directive or declarations are handled at compile time. Use of namespace does affect the readability of the program. So it should be used only when needed.

 

Summary

 

  • Namespace is a feature added in C++ and not present in C
  • A namespace is a declarative region that provides a scope to the identifiers (names of the types, function, variables etc) inside it
  • C++ allows unique names in a scope. Namespace enables using same names in different context without name conflict
  • The namespace definition must be done at global scope, or nested inside another namespace
  • Its syntax is somewhat like class syntax, but
  • Identifiers cannot have access specification (public, private, protected)
  • Namespace definition doesn’t terminate with a semicolon
  • One cannot create instance of namespace
  • Elements can be accessed using
  • Qualification name with scope resolution operator
  • Using directive ( importing all elements)
  • Using declaration (importing single element at a time)
  • With keyword ‘using’, names are imported in current scope where used
  • Namespaces are open – they can be in several independent header files
  • Namespace can be given alias name
  • Namespace can be anonymous, i.e. without name
  • Namespace can be extended to have additional elements
  • Namespace can be non-contiguous. Its definition can be continued and extended in same file or over multiple files, it is not redefined or overridden
  • Use of namespace do not incur any runtime overhead, but it may decrease readability

 

References

 

 

1) Stanley Lippmann, “C++ Primer”, Pearson Education.

2) Bjarne Stroustrup, “The C++ Programming Language”, Pearson Education.

3) Scott Mayer, “Effective C++”, Addison Wesley.

4) Bhushan Trivedi , Programming with ANSI C++, 2/e , Oxford University Press.

5) Yashavant P. Kanetkar “Let Us C++” , Bpb Publications.

6) Abhiram G. Ranade, “An Introduction to Programming through C++” , McGraw Hill

7) Ellis and B. Stroustrup “Annotated C++ Reference Manual”, http://www.stroustrup.com/arm.html

8) Herbert Schildt, “Complete Reference C++”, McGraw Hill Publications.

9) Ashok Kamthane, “Object Oriented Programming with ANSI and Turbo C++”, Pearson Education

10) E Balaguruswami, “Object Oriented Programming With C++”, Tata McGraw Hill

11) “C++ FAQs”, Pearson Education.