Namespaces
Namespaces provide a method for preventing name conflicts in large projects.
Table of Contents
- Name Collisions
- Standard Namespace
- Using Directives
- Scoped Using
- Namespace Aliases
- User Defined Namespaces
Name Collisions
By default, functions or classes defined in a C++ program become part of the global namespace. For large projects, especially those that use 3rd party libraries, there’s a chance that multiple things get defined with the same name.
For example, you may define a log()
function in your project and you might also include a library that defines a function called log()
. This will cause the linker to fail during compilation as it will not know which log()
function to use.
This type of conflict is called a name collision or a naming conflict.
Standard Namespace
When C++ was first created all of the identifiers in the standard library were defined in the global namespace. This lead to many name collisions. The solution was the creation of named scopes which are separate from each other and from the global namespace.
All of the standard library identifiers are now defined inside of the std
(short for standard) namespace. This is why, for example, we use std::cout
instead of cout
when outputting to the console.
🎵 Note:
The two colons that come after the namespace are called the scope resolution operator.
Using Directives
You may come across code that includes the using
directive, which instructs the compiler to look in specific namespaces by default:
#include <iostream>
using namespace std;
int main() {
cout << "Hello world!"; // cout no longer needs the std:: prefix.
}
💡 Best Practice:
Avoid the using
directive and always explicitly use identifiers with their namespace.
The using
directive effectively adds namespaces to the global scope, which defeats the entire point of having namespaces.
Scoped Using
A using
directive can be scoped to a block of code such that it doesn’t taint your entire code base:
#include <iostream>
int main() {
using namespace std; // We don't need to use the std:: prefix within main().
int number;
cout << "Pick a number: ";
cin >> number;
cout << "Hello " << number;
}
Although an improvement over a global using
directive, this still isn’t recommended.
Namespace Aliases
If you feel tempted to use a using
directive because of a namespace with a very long name, you can create a shorter alias for that namespace.
For example, let’s say you’re using a library with a library.h
header file that includes a namespace called supercalifragilisticexpialidocious
:
supercalifragilisticexpialidocious::prepareBattleStations();
supercalifragilisticexpialidocious::fireCannons();
supercalifragilisticexpialidocious::scanPerimeter();
You can write the following instead;
namespace supercali = supercalifragilisticexpialidocious;
supercali::prepareBattleStations();
supercali::fireCannons();
supercali::scanPerimeter();
User Defined Namespaces
You should get in the habit of creating your own namespaces when making your own internal libraries.
I’ve re-implemented the function headers example with a namespace:
🚀 Run the example code on Compiler Explorer!
🎵 Note:
The namespace
must be used in the header file and the associated cpp file.