In lesson 10.1 -- Introduction to dynamic memory allocation, we introduced the concept of naming collisions
and namespaces
. As a reminder, a naming collision occurs when two identical identifiers are introduced into the same scope, and the compiler can’t disambiguate which one to use. When this happens, compiler or linker will produce an error because they do not have enough information to resolve the ambiguity. As programs become larger, the number of identifiers increases linearly, which in turn causes the probability of a naming collision occurring to increase exponentially.
Let’s revisit an example of a naming collision, and then show how we can resolve it using namespaces. In the following example, foo.h
and goo.h
are the header files that contain functions that do different things but have the same name and parameters.
foo.cpp:
1 2 3 4 5 |
// This doSomething() adds the value of its parameters int doSomething(int x, int y) { return x + y; } |
goo.cpp:
1 2 3 4 5 |
// This doSomething() subtracts the value of its parameters int doSomething(int x, int y) { return x - y; } |
main.cpp:
1 2 3 4 5 6 7 8 9 |
#include <iostream> int doSomething(int x, int y); // forward declaration for doSomething int main() { std::cout << doSomething(4, 3) << '\n'; // which doSomething will we get? return 0; } |
If this project includes only foo.cpp
or goo.cpp
(but not both), it will compile and run without incident. However, by compiling both into the same program, we have now introduced two different functions with the same name and parameters into the same scope (the global scope), which causes a naming collision. As a result, the compiler will issue an error:
c:\VCProjects\goo.cpp(2) : error C2084: function 'int doSomething(int,int)' already has a body
Note that this error happens at the point of redefinition, so it doesn’t matter whether function doSomething
is ever called.
One way to resolve this would be to rename one of the functions, so the names no longer collide. But this would also requiring changing the names of all the function calls, which can be a pain, and is subject to error. For the same reason that the standard library was moved into the std
namespace, another way to avoid collisions is to put your functions into your own namespaces.
Defining your own namespaces
C++ allows us to define our own namespaces via the namespace
keyword. Namespaces that you create for your own declarations are called user-defined namespaces. Namespaces provided by C++ (such as the global namespace
) or by libraries (such as namespace std
) are not considered user-defined namespaces.
Namespace identifiers are typically non-capitalized.
Here is an example of the headers in the prior example rewritten using namespaces:
foo.h:
1 2 3 4 5 6 7 8 |
namespace foo // define a namespace named foo { // This doSomething() belongs to namespace foo int doSomething(int x, int y) { return x + y; } } |
goo.h:
1 2 3 4 5 6 7 8 |
namespace goo // define a namespace named goo { // This doSomething() belongs to namespace goo int doSomething(int x, int y) { return x - y; } } |
Now doSomething()
inside of foo.h
is inside the foo
namespace, and the doSomething()
inside of goo.h
is inside the goo
namespace. Let’s see what happens when we recompile our program.
main.cpp:
1 2 3 4 5 |
int main() { std::cout << doSomething(4, 3) << '\n'; // which doSomething will we get? return 0; } |
The answer is that we now get another error!
C:\VCProjects\Test.cpp(15) : error C2065: 'doSomething' : undeclared identifier
What happened is that when we tried to call the doSomething()
function, the compiler looked in the global namespace to see if it could find a definition of doSomething()
. However, because neither of our doSomething()
functions live in the global namespace any longer, it failed to find a definition for doSomething
!
There are two different ways to tell the compiler which version of doSomething()
to use, via the scope resolution operator
, or via using statements
(which we’ll discuss in a later lesson in this chapter).
Accessing a namespace with the scope resolution operator (::)
The best way to tell the compiler to look in a particular namespace for an identifier is to use the scope resolution operator (::). The scope resolution operator tells the compiler that the identifier specified by the right-hand operand should be looked for in the scope of the left-hand operand.
Here is an example of using the scope resolution operator to tell the compiler that we explicitly want to use the version of doSomething()
that lives in the foo
namespace:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <iostream> namespace foo // define a namespace named foo { // This doSomething() belongs to namespace foo int doSomething(int x, int y) { return x + y; } } namespace goo // define a namespace named goo { // This doSomething() belongs to namespace goo int doSomething(int x, int y) { return x - y; } } int main() { std::cout << foo::doSomething(4, 3) << '\n'; // use the doSomething() that exists in namespace foo return 0; } |
This produces the expected result:
7
If we wanted to use the version of doSomething()
that lives in goo
instead:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <iostream> namespace foo // define a namespace named foo { // This doSomething() belongs to namespace foo int doSomething(int x, int y) { return x + y; } } namespace goo // define a namespace named goo { // This doSomething() belongs to namespace goo int doSomething(int x, int y) { return x - y; } } int main() { std::cout << goo::doSomething(4, 3) << '\n'; // use the doSomething() that exists in namespace goo return 0; } |
This produces the result:
1
The scope resolution operator is great because it allows us to explicitly pick which namespace we want to look in, so there’s no potential ambiguity. We can even do the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <iostream> namespace foo // define a namespace named foo { // This doSomething() belongs to namespace foo int doSomething(int x, int y) { return x + y; } } namespace goo // define a namespace named goo { // This doSomething() belongs to namespace goo int doSomething(int x, int y) { return x - y; } } int main() { std::cout << foo::doSomething(4, 3) << '\n'; // use the doSomething() that exists in namespace foo std::cout << goo::doSomething(4, 3) << '\n'; // use the doSomething() that exists in namespace goo return 0; } |
This produces the result:
7 1
Scope resolution with no prefix
The scope resolution operator can also be used without any preceding namespace (eg. ::doSomething
). In such a case, the identifier (e.g. doSomething
) is looked for in the global namespace.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <iostream> void print() // this print lives in the global namespace { std::cout << " there\n"; } namespace foo { void print() // this print lives in the foo namespace { std::cout << "Hello"; } } int main() { foo::print(); // call foo::print() ::print(); // call print() in global namespace (same as just calling print() in this case) return 0; } |
So why would you actually want to do this? In most cases, you won’t. But we’ll see examples where this becomes useful in future lessons.
Multiple namespace blocks allowed
It’s legal to declare namespace blocks in multiple locations (either across multiple files, or multiple places within the same file). All declarations within the namespace are considered part of the namespace.
add.h:
1 2 3 4 5 6 7 8 |
namespace basicMath { // function add() is part of namespace basicMath int add(int x, int y) { return x + y; } } |
subtract.h:
1 2 3 4 5 6 7 8 |
namespace basicMath { // function subtract() is also part of namespace basicMath int subtract(int x, int y) { return x - y; } } |
main.cpp:
1 2 3 4 5 6 7 8 9 10 11 |
#include "add.h" // for basicMath::add() #include "subtract.h" // for basicMath::subtract() #include <iostream> int main() { std::cout << basicMath::add(4, 3) << '\n'; std::cout << basicMath::subtract(4, 3) << '\n'; return 0; } |
This works exactly as you would expect:
7 1
The standard library makes extensive use of this feature, as each standard library header file contains its declarations inside a namespace std
block contained within that header file. Otherwise the entire standard library would have to be defined in a single header file!
Note that this capability also means you could add your own functionality to the std
namespace. Doing so causes undefined behavior most of the time, because the std
namespace has a special rule, prohibiting extension from user code.
Warning
Do not add custom functionality to the std namespace.
Nested namespaces
Namespaces can be nested inside other namespaces. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> namespace foo { namespace goo // goo is a namespace inside the foo namespace { int add(int x, int y) { return x + y; } } } int main() { std::cout << foo::goo::add() << '\n'; return 0; } |
Note that because namespace goo
is inside of namespace foo
, we access g_x
as foo::goo::g_x
.
In C++17, nested namespaces can also be declared this way:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> namespace foo::goo // goo is a namespace inside the foo namespace (C++17 style) { int add(int x, int y) { return x + y; } } int main() { std::cout << foo::goo::add() << '\n'; return 0; } |
Namespace aliases
Because typing the fully qualified name of a variable or function inside a nested namespace can be painful, C++ allows you to create namespace aliases, which allow us to temporarily shorten a long sequence of namespaces into something shorter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <iostream> namespace foo { namespace goo { int add(int x, int y) { return x + y; } } } int main() { namespace boo = foo::goo; // boo now refers to foo::goo std::cout << boo::add() << '\n'; // This is really foo::goo::add() return 0; } // The boo alias ends here |
One nice advantage of namespace aliases: If you ever want to move the functionality within foo::goo
to a different place, you can just update the boo
alias to reflect the new destination, rather than having to find/replace every instance of foo::goo
.
It’s worth noting that namespaces in C++ were not originally designed as a way to implement an information hierarchy -- they were designed primarily as a mechanism for preventing naming collisions. As evidence of this, note that the entirety of the standard library lives under the singular namespace std::
(with some nested namespaces used for newer library features). Some newer languages (such as C#) differ from C++ in this regard.
In general, you should avoid deeply nested namespaces.
When you should use namespaces
In applications, namespaces can be used to separate application-specific code from code that might be reusable later (e.g. math functions). For example, physical and math functions could go into one namespace (e.g. math::
). Language and localization functions in another (e.g. lang::
).
When you write a library or code that you want to distribute to others, always place your code inside a namespace. The code your library is used in may not follow best practices -- in such a case, if your library’s declarations aren’t in a namespace, there’s an elevated chance for naming conflicts to occur. As an additional advantage, placing library code inside a namespace also allows the user to see the contents of your library by using their editor’s auto-complete and suggestion feature.
Variables in namespaces
In all of the examples above, we’ve shown functions defined in user-defined namespaces. But namespaces can also contain global variables. You can see examples of this in upcoming lesson %Failed lesson reference, id 9391%.
![]() |
![]() |
![]() |
This tutorial is really very helpful.Thanks Alex.
one comment on the header files included in the main.cpp
User defined header files should be in double quotes(ex: #include "a.h") otherwise compiler will throw an error.
Fantastic tutorial, I'm really enjoying it - thank you very much for sharing your knowledge, Alex. At this point of tutorial, I have a question:
I followed the examples in this section, and found out everything works fine when using scope resolution operator:
double dSin = 0.0;
double dCos = 0.0;
foo::GetSinCos(30.0, dSin, dCos);
cout << "The sin is " << dSin << endl;
cout << "The cos is " << dCos << endl;
But when I try the "using namespace" keyword method, I get "ambiguous call to overloaded function" error:
double dSin = 0.0;
double dCos = 0.0;
using namespace foo;
GetSinCos(30.0, dSin, dCos);
cout << "The sin is " << dSin << endl;
cout << "The cos is " << dCos << endl;
Does anyone have an idea why is this happening? Thanks :)
I'm confused! Consider "cin", for example. It is in the namespace std. Is there any other namespaces with object "cin"? Otherwise, why we need to declare the namespace std::cin.
In other words, would you please give me an example for two standard objects with the same name in different namespaces? (I mean an object that is not defined by user)
He used the 'std::cin' as an example to show you how it works.
also, while I'm not aware of such colliding cases, it might be possible that custom namespaces have colliding names, and this is when it might come useful.
nice work!!
well.. this didn't seem like the hardest section (pointers was a hard concept for someone new to cpp), yet for some reason I cant get this to work!
I'm also confused that you mention the header files, but then the functions that you use in the header files don't look like simple prototypes, since they have a return statements, they look like full functions ..hmm
The simplified example is below:
header.h:
#ifndef ...etc
externalFn.cpp:
so in my main.cpp, I should just be able to use:
main.cpp :
but the only error I get is: undefined reference to 'exf::bx()'
I dont understand why, should we actually be defining the full functions (not just the proto) in the header files now?
(The rest of this tutorial has been great by the way... Thank you so much for sharing your wealth of knowledge and teaching skills ;) )
I'm not certain why, but removing the inline option (learnt in the previous lesson) solved my problem.
my question
How to get the out put in GUI for C++ Programing?
In this function, the number of arguments is zero
but in
The number of arguments is not know[infinity].