Contents
Namespaces
Introduction to Namespaces in C++
A namespace in C++ provides a context where you can declare identifiers such as variables, methods, and classes. It helps in organizing code and avoiding name collisions. For instance, if your code has a function named xyz()
and a library also has a function with the same name, the compiler will not be able to distinguish between the two without namespaces. A namespace helps resolve this issue by adding context to the function, class, or variable name.
A namespace essentially defines a scope, and one of its major benefits is preventing name collisions. A well-known example is the std
namespace in the C++ Standard Library, where various classes, methods, and templates are defined. While coding in C++, we commonly use using namespace std;
to access these elements without needing to prefix std::
to each function call or variable access.
Defining a Namespace
To declare a namespace, use the namespace
keyword followed by the namespace name:
namespace my_namespace {
int variable;
void function();
class MyClass {};
}
No semicolon is needed after the closing brace of a namespace definition. To access elements within the namespace, use the following syntax:
my_namespace::variable;
my_namespace::function();
Using the using
Directive
The using
directive allows you to avoid specifying the namespace every time you use a variable or function. By writing using namespace my_namespace;
, you tell the compiler that all identifiers in the code are from the given namespace.
#include
using namespace std;
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
using namespace first_space;
int main() {
func(); // This calls the function from first_space
return 0;
}
Output:
Inside first_space
The using
directive applies from the point where it’s used until the end of the scope. If another entity with the same name exists in a broader scope, it gets hidden.
Nested Namespaces
Namespaces can also be nested, where one namespace is defined within another. For example:
namespace outer {
namespace inner {
void func() {
std::cout << "Inside inner namespace" << std::endl;
}
}
}
Output:
Inside second_space
Scope of Entities in a Namespace
Entities, such as variables and functions, defined in a namespace are scoped within that namespace. This means you can have entities with the same name in different namespaces without causing errors.
#include
using namespace std;
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
int main() {
first_space::func(); // Calls function from first_space
second_space::func(); // Calls function from second_space
return 0;
}
Output:
Inside first_space
Inside second_space
Namespaces in Practice
Consider the following code that demonstrates the error caused by using two variables with the same name in the same scope:
int main() {
int value;
value = 0;
double value; // Error: redeclaration of 'value'
value = 0.0;
}
Error:
Compiler Error: 'value' has a previous declaration as 'int value'
With namespaces, you can declare two variables with the same name in different namespaces without conflict:
#include
using namespace std;
namespace first_space {
int val = 500;
}
int val = 100;
int main() {
int val = 200;
cout << first_space::val << endl;
return 0;
}
Output:
ns::Geek::display()
Alternatively, a class can be declared inside a namespace and defined outside the namespace:
#include
using namespace std;
namespace ns {
class Geek;
}
class ns::Geek {
public:
void display() {
cout << "ns::Geek::display()" << endl;
}
};
int main() {
ns::Geek obj;
obj.display();
return 0;
}
Output:
ns::Geek::display()
Namespaces in C++ (Set 2: Extending and Unnamed Namespaces)
Defining a Namespace:
A namespace definition in C++ starts with the namespace
keyword followed by the name of the namespace, like so:
namespace my_namespace
{
// Variable declarations
int my_var;
// Method declarations
void my_function();
// Class declarations
class MyClass {};
}
Note that there is no semicolon after the closing brace of the namespace definition. To use variables or functions from a specific namespace, prepend the namespace name with the scope resolution operator (::
), like this:
my_namespace::my_var;
my_namespace::my_function();
The using
Directive:
To avoid manually prepending the namespace name each time, you can use the using namespace
directive. This tells the compiler to implicitly use the names from the specified namespace:
#include
using namespace std;
// Define namespaces
namespace first_space
{
void func()
{
cout << "Inside first_space" << endl;
}
}
namespace second_space
{
void func()
{
cout << "Inside second_space" << endl;
}
}
using namespace first_space;
int main()
{
func(); // Calls the function from first_space
return 0;
}
The names introduced by the using
directive follow normal scoping rules. Once introduced, they are visible from the point of the directive to the end of the scope where it was used.
Nested Namespaces:
You can also define namespaces within other namespaces, referred to as nested namespaces:
namespace outer_space
{
namespace inner_space
{
void func()
{
// Function inside inner_space
}
}
}
To access members of a nested namespace, use the following syntax:
using namespace outer_space::inner_space;
If you only use outer_space
, it will also make the inner namespace available in scope:
#include
using namespace std;
namespace outer_space
{
void outer_func()
{
cout << "Inside outer_space" << endl;
}
namespace inner_space
{
void inner_func()
{
cout << "Inside inner_space" << endl;
}
}
}
using namespace outer_space::inner_space;
int main()
{
inner_func(); // Calls function from inner_space
return 0;
}
Creating Multiple Namespaces:
It’s possible to create multiple namespaces with different names in the global scope. Here’s an example:
#include
using namespace std;
// First namespace
namespace first
{
int func() { return 5; }
}
// Second namespace
namespace second
{
int func() { return 10; }
}
int main()
{
cout << first::func() << endl; // Calls func() from first namespace
cout << second::func() << endl; // Calls func() from second namespace
return 0;
}
Output:
5
10
Extending Namespaces:
It is possible to define a namespace in parts using the same name more than once. Essentially, the second block is an extension of the first:
#include
using namespace std;
namespace first
{
int val1 = 500;
}
namespace first
{
int val2 = 501;
}
int main()
{
cout << first::val1 << endl; // Accesses first part of the namespace
cout << first::val2 << endl; // Accesses second part of the namespace
return 0;
}
Output:
500
501
Unnamed Namespaces:
Unnamed namespaces allow you to define identifiers that are unique to the file they are declared in. They can be seen as a replacement for the old static
keyword for file-scope variables. In unnamed namespaces, no namespace name is provided, and the compiler generates a unique name for it:
#include
using namespace std;
namespace
{
int rel = 300;
}
int main()
{
cout << rel << endl; // Prints 300
return 0;
}
Output:
300
Namespace in C++ | Set 3 (Accessing, creating header, nesting and aliasing)
Different Ways to Access Namespaces in C++
In C++, there are multiple ways to access variables and functions within a namespace. Here’s an explanation with modified examples.
Defining a Namespace
A namespace definition starts with the namespace
keyword followed by the name of the namespace, as shown below:
namespace my_namespace
{
// Variable declaration
int my_var;
// Function declaration
void my_function();
// Class declaration
class MyClass {};
}
There is no semicolon after the closing brace. To access variables or functions from the namespace, use the following syntax:
my_namespace::my_var; // Access variable
my_namespace::my_function(); // Access function
The using
Directive
To avoid repeatedly writing the namespace name, you can use the using namespace
directive. This informs the compiler to assume that all names used after the directive come from the specified namespace:
#include
using namespace std;
// First namespace
namespace first_ns
{
void display()
{
cout << "Inside first_ns" << endl;
}
}
// Second namespace
namespace second_ns
{
void display()
{
cout << "Inside second_ns" << endl;
}
}
using namespace first_ns;
int main()
{
display(); // Calls the function from first_ns
return 0;
}
In this case, the function from first_ns
will be called because of the using
directive.
Nested Namespaces
Namespaces can be nested, meaning you can define one namespace inside another:
namespace outer_ns
{
void outer_function() {}
namespace inner_ns
{
void inner_function() {}
}
}
You can access members of a nested namespace using the following syntax:
using namespace outer_ns::inner_ns;
Alternatively, you can also use a more hierarchical approach:
#include
using namespace std;
// Outer namespace
namespace outer_ns
{
void outer_function()
{
cout << "Inside outer_ns" << endl;
}
// Inner namespace
namespace inner_ns
{
void inner_function()
{
cout << "Inside inner_ns" << endl;
}
}
}
using namespace outer_ns::inner_ns;
int main()
{
inner_function(); // Calls the function from inner_ns
return 0;
}
Accessing Namespace Members
1. Accessing Normally : You can access members of a namespace using the scope resolution operator (::
)
#include
using namespace std;
namespace sample_ns
{
int number = 100;
}
int main()
{
cout << sample_ns::number << endl; // Accesses variable with scope resolution
return 0;
}
Output:
100
2. Using the using
Directive : You can also use the using
directive to make variables and functions directly accessible:
#include
using namespace std;
namespace sample_ns
{
int number = 100;
}
// Use of 'using' directive
using namespace sample_ns;
int main()
{
cout << number << endl; // Accesses variable without scope resolution
return 0;
}
Example:
100
Using Namespaces Across Files
Namespaces can be defined in one file and accessed from another. This can be done as follows:
File 1 (header file):
// file1.h
namespace sample_ns
{
int getValue()
{
return 50;
}
}
File 2 (source file):
// file2.cpp
#include
#include "file1.h" // Including file1.h
using namespace std;
int main()
{
cout << sample_ns::getValue(); // Accessing function from file1.h
return 0;
}
This allows the function declared in file1.h
to be used in file2.cpp
.
Nested Namespaces
In C++, namespaces can also be nested, meaning one namespace can be declared inside another:
#include
using namespace std;
// Outer namespace
namespace outer_ns
{
int value = 10;
namespace inner_ns
{
int inner_value = value; // Access outer_ns::value
}
}
int main()
{
cout << outer_ns::inner_ns::inner_value << endl; // Outputs 10
return 0;
}
Output:
10
Namespace Aliasing
You can create an alias for a namespace to simplify its usage. The syntax for aliasing is as follows:
#include
namespace long_name_space
{
namespace nested_space
{
namespace deep_space
{
int data = 99;
}
}
}
// Alias for nested namespaces
namespace short_name = long_name_space::nested_space::deep_space;
int main()
{
std::cout << short_name::data << std::endl; // Access data using alias
return 0;
}
Output:
99