In lesson 2.8 -- Naming collisions and an introduction to namespaces, 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.cpp
and goo.cpp
are the source 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 contains 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 linker will issue an error:
goo.cpp:3: multiple definition of `doSomething(int, int)'; foo.cpp:3: first defined here
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 require changing the names of all the function calls, which can be a pain, and is subject to error. A better way to avoid collisions is to put your functions into your own namespaces. For this reason the standard library was moved into the std
namespace.
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 files in the prior example rewritten using namespaces:
foo.cpp:
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.cpp:
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.cpp
is inside the foo
namespace, and the doSomething()
inside of goo.cpp
is inside the goo
namespace. Let’s see what happens when we recompile our program.
main.cpp:
1 2 3 4 5 6 7 |
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; } |
The answer is that we now get another error!
ConsoleApplication1.obj : error LNK2019: unresolved external symbol "int __cdecl doSomething(int,int)" ([email protected]@[email protected]) referenced in function _main
In this case, the compiler was satisfied (by our forward declaration), but the linker could not find a definition for doSomething
in the global namespace. This is because both of our versions of doSomething
are no longer in the global namespace!
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).
For the subsequent examples, we’ll collapse our examples down to a one-file solution for ease of reading.
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.
circle.h:
1 2 3 4 5 6 7 8 9 |
#ifndef CIRCLE_H #define CIRCLE_H namespace basicMath { inline constexpr double pi{ 3.14 }; } #endif |
growth.h:
1 2 3 4 5 6 7 8 9 10 |
#ifndef GROWTH_H #define GROWTH_H namespace basicMath { // the constant e is also part of namespace basicMath inline constexpr double e{ 2.7 }; } #endif |
main.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "circle.h" // for basicMath::pi #include "growth.h" // for basicMath::e #include <iostream> int main() { std::cout << basicMath::pi << '\n'; std::cout << basicMath::e << '\n'; return 0; } |
This works exactly as you would expect:
3.14 2.7
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.
When you separate your code into multiple files, you’ll have to use a namespace in the header and source file.
add.h
1 2 3 4 5 6 7 8 9 10 |
#ifndef ADD_H #define ADD_H namespace basicMath { // function add() is part of namespace basicMath int add(int x, int y); } #endif |
add.cpp
1 2 3 4 5 6 7 8 9 10 |
#include "add.h" namespace basicMath { // define the function add() int add(int x, int y) { return x + y; } } |
main.cpp
1 2 3 4 5 6 7 8 9 10 |
#include "add.h" // for basicMath::add() #include <iostream> int main() { std::cout << basicMath::add(4, 3) << '\n'; return 0; } |
If the namespace is omitted in the source file, the linker won’t find a definition of basicMath::add
, because the source file only defines add
(global namespace). If the namespace is omitted in the header file, “main.cpp” won’t be able to use basicMath::add
, because it only sees a declaration for add
(global 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(1, 2) << '\n'; return 0; } |
Note that because namespace goo
is inside of namespace foo
, we access add
as foo::goo::add
.
Since 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(1, 2) << '\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 |
#include <iostream> namespace foo::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(1, 2) << '\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.
![]() |
![]() |
![]() |
Hi, I got an error says: undefined reference to `basicMath::add(int, int)' collect2.exe: error: ld returned 1 exit status. I'm sure the code is correct, with no typing errors. How can I solve this problem?
Is there anyway to define namespace for a whole file? I don't like to have multiple nested block.
What's your point? This lesson explicitly describes global namespaces.
Hi. I'm curious as to whether we must add namespaces to the source files (add.cpp and main.cpp) and header file altogether? Wouldnt the code still work fine as discussed in the "working with multiple files" chapter?
As explained, I think it is reasonable to add a namespace in a file for definition, with the same namespace in the header file for declaration.
Why you want to add the same namespace again in the main file?
I mean we could have just declared the function add alone without a specific namespace, and then have called add(3,4) without “basicMath::” in main.cpp. It would still work
Now I got you.
No it is not like you "must" do it.
Check the last title (why you should use user namespace).
this code won't work unless you forward declare namespace with function prototype in it:
main.cpp:
add.cpp:
so yes, you must add add namespaces to the source files (add.cpp and main.cpp) and header file altogether
When you declare a nested namespace like
, is it best practice to have the contents double indented like it is shown?
No, use an auto-formatter, it will format it properly.
"If the namespace is omitted in the source file, the linker won’t find a definition of basicMath::add, because the source file only defines add (global namespace). If the namespace is omitted in the header file, “main.cpp” won’t be able to use basicMath::add, because it only sees a declaration for add (global namespace)."
What do you mean by saying (global namespace)? Do you mean the linker will look for the declaration/definition in the global namespace?
The "(global namespace)" means that `add` is defined in the global namespace in the source file.
`main()` called `basicMath::add`, so the linker searches for `add` in the `basicMath` namespace. It's not there, so you get an error.
I am sorry I think I missed something,
why can't I define my function in the namespace that's in my header file instead of putting only the declaration for it?
You'd violate the one-definition-rule by defining functions in headers. This is unrelated to namespaces. If you include the header in more than 1 source file, you'll get a linker error.
Would you please give an example of or explain the following? I didn't catch it!
'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.'
Take this example.
If you decided that you wanted to move addThenSubtractOne() to the version2 namespace, then all you have to do is move the function into the namespace, and change the alias.
If you didn't use an alias, you would've written version1::awaitingApproval::addThenSubtractOne three different times, and you would have to change each of those instances when you moved the function to the version2 namespace.
That clears it up, thank you
First I wanted to thank you for such an amazing tutorial!
According to the following code, if we want to define a variable belong to namespace 'foo' not 'goo' then how should they be defined?
Either don't use the short syntax and next `goo` inside `foo`
Or add another namespace black
These are identical.
Hey,
What do you mean by "the source file", add.cpp or main.cpp?
'If the namespace is omitted in the source file, the linker won’t find a definition of basicMath::add'
"the source file" refers to "add.cpp".
I didn't include "add.h" in the file add.cpp, but I didn't get any link error. Why?
"If the namespace is omitted in the source file, the linker won’t find a definition of basicMath::add, because the source file only defines add (global namespace). If the namespace is omitted in the header file, “main.cpp” won’t be able to use basicMath::add, because it only sees a declaration for add (global namespace)."
"add.cpp" doesn't need the forward declarations that are in the header, your code works fine without the include. The include is only in the .cpp file for reasons mentioned in the lesson about headers.
The text your quoted is unrelated to this, you must be confusing something.
Hi,
1) "Note that this capability also means you could add your own functionality to the std namespace.
Do those sentences mean we could use a namespace named "std" for our own use, right?
2) "...because the std namespace has a special rule, prohibiting extension from user code. "
what does "prohibiting extension from user code" mean?
I did that and I didn't get any warning or error!
1) It would be the same namespace.
2) Undefined behavior isn't required to cause any warnings or errors. It's undefined what happens. Anything can happen.
Hello,
I have two question:
1)In your very first example, if I wanted to still have two separate foo.cpp and goo.cpp source files, and make the compiler aware of those namespace inside main.cpp, what would we do?
2)
what does that sentence mean? Can we also have both definitions and declarations inside a namespace?
I think I should define the following in main.cpp:
main.cpp:
You should move line 1-4 into foo.h and line line 5-8 into goo.hpp. That way you can use the functions without having to write forward declarations everywhere.
Hi ! Thanks for all those C++ tutorials, it really helps me ;)
However, i noticed that there is no ambuigity for my really simple ( test ) program:
I just don't really understand why i can avoid the std:: before calling the function sqrt() from cmath, could you explain me ? :)
Some headers in C++ are backwards compatible with C (which didn't have namespaces), so you can use their contents without `std::`. Since we're not in C, we recommend using the `std::` prefix.
Ok thanks ! I'll use std:: even if it's not necessary, it will be more clear for me :)
I wanted to know if the error message : "goo.cpp:3: multiple definition of `doSomething(int, int)'; foo.cpp:3: first defined here",
is compile error or linker error, if it is compile error, can you please correct the line "As a result, the linker will issue an error:" ?
The compiler works on individual files (Including headers in that file), it doesn't know about anything in other files. The linker detects duplicate definitions across files.
Hello,I got a question about nested namespaces .you generally introduced two ways to do so. I'm gonna use the first method in the example below:
so if I utilize the second method(c++17 style) how must I define two different functions that each of them belongs to one of the namespaces(one to foo,and another to goo)?
because there is no block {} separating goo from foo.
thanks in advance!.
The C++17 style doesn't replace the old, it's an addition. If you want the use the C++17 style in this example, you'd have 2 separate namespace blocks
Hi nascardriver!
Found two typos. In the first section, near the end, there's a sentence "But this would also requiring changing the names of all the function calls", should be "require" instead of "requiring".
and the second one is in "defining your own namespaces", "Here is an example of the headers in the prior example rewritten using namespaces", they are source files, not headers.
One other thing. Up until this lesson, whenever I created a new project, I'd disable my compiler extensions and set my language standard to the latest draft in project properties as suggested by you guys. But when I did this, I couldn't use conditional compilation directives "ifndef as header guard as suggested, giving me the error "C 1004: unexpected end-of-file found" . So I'd usually resort to #pragma. But this time around, I decided to not disable my language extensions and then recompiled the program (with language standard set to the latest). It worked just fine! Does this mean that #ifndef is not part of the C++ standard?
The last thing I wanna mention is that when I wanted to do the first exercise, I put my goo and foo functions inside two namespaces named goo and foo respectively and then put them in different .cpp files. And to call foo from main.cpp, I created a namespace named foo, within which I put the function prototype for doSomething() and placed it inside main.cpp. Should I put the namespace with the prototype inside a header file or should I leave it just the way it is?
This is what I did in main:
namespace foo
{
int doSomething(int x, int y); // should I put this whole namespace inside a header?
}
int main()
{
//std::cout << doSomething(4, 3) << '\n'; this wouldn't compile, so I used the namespace above
std::cout <<foo::doSomething(12, 11) << '\n';
}
By the way, I'm using Visual studio 2017.
Typos fixed, thanks!
`#pragma once` in non-standard. Your error message sounds like you forgot the `#endif` at the end of the file.
The declarations should go in a header with the same name as the source file.
You're welcome. I checked my code to see if I forgot #endif at the end.But I haven't.This is how I wrote my header:
#ifndef GROWTH_H
#define GROWTH_H
namespace basicMath
{
constexpr double e{ 2.7 };
}
#endif
Also, could you teach me how to put my code inside code tags? No matter what I do, it just doesn't work:(
Does your code compile if you add an empty line after the `#endif`? The empty line is no longer required, but there might be a compiler option that makes your compiler complain about the missing line.
[-code]
mike
[-/code]
without the -
If you edit your comment, code tags work after refreshing the page.
Thanks. I added the line but it didn't work. I removed it but still didn't work.
"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 6.8 -- Global constants and inline variables."
However, the sub-section "Multiple namespace blocks allowed" examples use inline constexpr variables.
Thanks! That was my bad, I didn't read the end of the lesson when I added the example with variables. If you don't mind giving me a quick feedback, was the example with variables surprising or difficult to understand? If so, I'll change it to functions. For now, I've removed the sentence at the end of the lesson.
It makes sense to me, a good callback to section 4.13 on symbolic constants.
Thank you for these tutorials.. I've read a few C++ tutorials before but never go the hang of some of the concepts (like why bit manipulation even exists), but the writing and explanation style of these tutorials are excellent. I noticed here you are using: #if !defined(ADD_H) in the header file - which I wasn't expecting as before you introduced only ifndef and you usually explain the options and advise which is best practice. Just something I noticed & had to websearch. Thanks again..
Fixed. Thanks!
Just wanted to point out a few things. In the example of "Scope Resolution with no prefix" , you add two colons before print(::print). Is there any reason of these colons?
Lastly, in the last examples you didn't add arguments in the function call of add(). Just pointing out.
You don't need `::print()` in this example, plain `print()` would do the same. You'd only need `::print()` if the code was inside of a scope where there's another entity called `print` (eg. inside the namespace `foo`).
I added the missing arguments, thanks for pointing them out :)
Is the directive #include"add.h" in the file add.cpp required?
(In "Multiple namespace blocks allowed)
We dont need declaration for a definition file.or do we??
We don't need it, but it can be beneficial in detecting errors early.
"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!"
I don't understand, why? What's the difference in using multiple header files for the library and using a single header file?
With multiple files you only have to pull in what you need. If there were only a single header, you'd have to pull in (and compile) everything in the standard library whether you used it or not!