First year students always have to been explained that it’s okay to reuse the same name for local variables in different functions or methods. Imagine if this were not the case: each time you’d have to make sure the name you chose is unique across potentially thousands of lines of code.
Fortunately, names are scoped, i.e., the scope of an identifier is the part of the code in which the identifier "lives". You can reuse the same identifier as long as their scopes don’t overlap. If there is overlap, there are certain rules that determine what the identifier refers to.
For example,
int x;
struct Foo
{
int x;
void foo()
{
int x;
}
}
There are three variables, all bound to the same identifier x
.
Their scopes also overlap. Inside foo
, the following rules apply:
-
x
refers to the local variable. -
To access the field, one can use
this→x
. -
The global variable is reachable through
::x
.
Type identifiers are more problematic though: by default, `struct`s and `class`es are all defined in the global scope, which means their scope always overlap.
Therefore, name clashes are a potential problem: you need to take care to assign a unique name to each of your types. When working in large teams or with external code (i.e., libraries), this can become a serious issue. Note that function are less likely to suffer from this problem thanks to overloading.
Enter namespaces.
A namespace is similar to Java’s packages: one can define multiple classes with the same name, as long as they are in different namespaces.
However, in Java, anything in a package foo
must be placed in a directory named foo
.
No such restriction exists in C++:
-
A file can contain any namespace it wants.
-
A file can contain any number of namespaces it wants.
The syntax is as follows:
namespace my_namespace
{
void my_function();
struct my_type
{
void my_method();
};
}
void my_namespace::my_function() { ... }
void my_namespace::my_type::my_method() { ... }
To refer to something in a namespace, you simply prefix it with ns::
where ns
is the name of the namespace.
An example you already encountered is the std
namespace: std::cout
, std::vector<int>
, etc.
#include "header-file.h"
void some_other_function()
{
my_namespace::my_function();
my_namespace::my_type local_variable;
local_variable.my_method();
}