Accessing Names in Namespaces
Qualification reaches a name through the namespace that contains it, as in std::cout and My_code::main.
Why Programs Need Separate Places for Names
Imagine a large program written by several teams. One team writes a function called main in their own part of the code, and another team's library also contains a name that looks identical. If every name were placed in one shared pool, the program would have no way to tell these apart. Namespaces solve this problem by giving names a place to live. This article is about the two everyday ways a program reaches a name that lives somewhere other than where the code currently sits.
A helpful way to picture a namespace is as a labeled drawer. Each drawer holds names, and the label on the drawer keeps names with the same spelling from getting mixed up when they belong to different drawers. A name stored in one drawer is not automatically visible from another drawer. To use it, you have to say which drawer it is in, or you have to set things up so that the drawer's contents can be looked at without repeating the label each time.
Where the Real main() Lives
The real main() is not wrapped in a named group the way My_code::main is. It lives in the global namespace, which is the outermost level of the program. It is not inside a named namespace, a class, or a function. Because it sits at the outermost level, it is reached without any namespace prefix. A name that is not inside any named group is effectively a global name, so the absence of a prefix tells you something about where a name is defined.
Look at the diagram and notice that the name main appears twice. One entry is in the global namespace and the other is inside My_code. These are two different entries that happen to share a spelling. Keeping this picture in mind makes the next step easier to follow, because the question becomes which of the two entries a given prefix selects.
Reaching a Name Through Its Namespace
The most direct way to access a name that belongs to another namespace is to qualify it with the namespace's name. Qualification means writing the namespace name, then the scope operator, then the name you want. The full path tells the program exactly which drawer to open. The source uses two examples: std::cout, where cout is looked up inside the namespace called std, and My_code::main, where main is looked up inside the namespace called My_code. In both cases the prefix removes any doubt about which name is meant, even when a different name with the same spelling exists elsewhere.
- std::cout names the cout entity inside the std namespace
- My_code::main names the main entity inside the My_code namespace, not the real
main()
Notice that the rule is the same for both lines. The program does not guess which cout or main you meant. The prefix before the scope operator names the drawer, and the name after it names the item inside that drawer.
Tracing a Qualified Lookup Step by Step
Looking up My_code::main
A program contains a global main() and a My_code namespace that also contains a main. The code refers to My_code::main. Which entry does the program use?
- 1Read the prefix
The prefix is My_code, so the program knows the search must happen inside the My_code namespace.
- 2Apply the scope operator
The scope operator separates the namespace name from the name being requested, so the program looks for main inside My_code.
- 3Ignore the global entry
The global
main()is in a different drawer. Because the prefix chose My_code, that entry is not the one selected. - 4Select the match
The entry found is the main inside My_code, which is the one the diagram showed as a separate entry.
My_code::main selects the main inside My_code unambiguously, even though a global main also exists.
What do you think happens?
Where does the real main() live: inside My_code, or in the global namespace?
Reveal answer
In the global namespace
The real main() is not inside a named namespace, class, or function. It sits at the outermost level, which is why it needs no namespace prefix.
Opening a Drawer with a Using-Directive
Qualifying every name works, but it can become tedious when a program uses many names from the same namespace. To gain access to names in the standard-library namespace, the source introduces a using-directive, written as using namespace std;. Its role is to make names from that namespace available to the code without requiring the full qualified path each time. A using-directive is therefore a way of opening a drawer for the code that follows, rather than a way of moving the names out of the drawer.
std::cout << "Hello";cout is reached only through the full path std::cout
using namespace std; cout << "Hello";
after the using-directive, cout is visible as a bare name
Mistakes Beginners Make with Namespace Prefixes
Common mistake Assuming a name from one namespace is visible from another without any prefix or directive
What it looks likeWriting cout alone in a program that has no using-directive for std
Why it failsA name stored in one drawer is not automatically visible from another drawer.
Do this insteadQualify the name as std::cout, or add a using-directive if many names from std are needed.
Common mistake Thinking the real main() needs a prefix because it is the important function
What it looks likeWriting a prefix in front of the real main() as though it were inside a named group
Why it failsThe real
main()lives in the global namespace, at the outermost level, so no prefix is used to reach it.Do this insteadRefer to the real main() without any namespace prefix.
Common mistake Believing a using-directive moves names out of the standard-library namespace
Why it failsThe directive only makes names visible to the code that follows; the original namespace is left unchanged.
Do this insteadThink of the directive as opening a drawer for the code, not emptying it.
Practice: Choosing the Right Way to Reach a Name
A program has a global main() and a namespace called My_code that also contains a main. Explain in your own words how the program can tell which main is meant when the code writes My_code::main, and then say which main a bare call to main() refers to.
Hints
- Look at which drawer the prefix names before deciding which entry is selected.
- Recall where the real
main()lives and whether it needs a prefix.
Key Takeaways in One Pass
- 1A name in another namespace is reached by qualifying it with the namespace name, the scope operator, and then the name, as in std::cout and My_code::main.
- 2The real
main()lives in the global namespace, not inside a named namespace, class, or function, which is why it is used without a prefix. - 3A using-directive gives access to standard-library names without the full qualified form each time, and it leaves the original namespace unchanged.
At a glance
- A name in another namespace is reached by qualifying it with that namespace's name and the scope operator, as in std::cout and My_code::main.
- The real
main()lives in the global namespace, not inside a named namespace, class, or function, so it is reached without a prefix. - A using-directive makes standard-library names available without repeating the qualified form, and it leaves the original namespace unchanged.