- C++ Fundamentals
- Antonio Mallia Francesco Zoffoli
- 830字
- 2021-06-11 13:36:00
Namespaces
One of the goals of functions is to better organize our code. To do so, it is important to give meaningful names to them.
For example, in package management software, there might be a function called sort for sorting packages. As you can see, the name is the same as the function that would sort a list of numbers.
C++ has a feature that allows you to avoid these kinds of problems and groups names together: namespaces.
A namespace starts a scope in which all the names declared inside are part of the namespace.
To create a namespace, we use the namespace keyword, followed by the identifier and then the code block:
namespace example_namespace {
// code goes here
}
To access an identifier inside a namespace, we prepend the name of the namespace to the name of the function.
Namespaces can be nested as well. Simply use the same declaration as before inside the namespace:
namespace parent {
namespace child {
// code goes here
}
}
To access an identifier inside a namespace, you prepend the name of the identifier with the name of the namespace in which it is declared, followed by ::.
You might have noticed that, before we were using std::cout. This is because the C++ standard library defines the std namespace and we were accessing the variable named cout.
To access an identifier inside multiple namespaces, you can prepend the list of all the namespaces separated by :: – parent::child::some_identifier. We can access names in the global scope by prepending :: to the name—::name_in_global_scope.
If we were to only use cout, the compiler would have told us that the name does not exist in the current scope.
This is because the compiler searches only in the current namespace and the parent namespaces to find an identifier by default, so unless we specify the std namespace, the compiler will not search in it.
C++ helps make this more ergonomic with the help of the using declaration.
The using declaration is defined by the using keyword, followed by an identifier specified with its namespaces.
For example, using std::cout; is a using declaration that declares that we want to use cout. When we want to use all the declarations from a namespace, we can write using namespace namespace_name;. For example, if we want to use every name defined in the std namespace, we would write: using namespace std;.
When a name is declared inside the using declaration, the compiler also looks for that name when looking for an identifier.
This means that, in our code, we can use cout and the compiler will find std::cout.
A using declaration is valid as long as we are in the scope in which it is declared.
Note
To better organize your code and avoid naming conflicts, you should always put your code inside a namespace that's specific to either your application or library.
Namespaces can also be used to specify that some code is used only by the current code.
Let's imagine you have a file called a.cpp that contains int default_name = 0; and another file called b.cpp with int default_name = 1;. When you compile the two files and link them together, we get an invalid program: the same variable has been declared with two different values, and this violates the One Definition Rule (ODR).
But you never meant for those to be the same variable. To you, they were some variables that you just wanted to use inside your .cpp file.
To tell that to the compiler, you can use anonymous namespaces: a namespace with no identifier.
All the identifiers created inside it will be private to the current translation unit (normally the .cpp file).
How can you access an identifier inside an anonymous namespace? You can access the identifier directly, without the need to use the namespace name, which does not exist, or the using declaration.
Note
You should only use anonymous namespaces in .cpp files.
Activity 5: Organizing Functions in Namespaces
Write a function to read the name of a car for a lottery in a namespace based on numerical input. If the user inputs 1, they win a Lamborghini, and if the user inputs 2, they win a Porsche:
- Define the first namespace as LamborghiniCar with an output() function that will print "Congratulations! You deserve the Lamborghini." when called.
- Define the second namespace as PorscheCar with an output() function that will print "Congratulations! You deserve the Porsche." when called.
- Write a main function to read the input of numbers 1 and 2 into a variable called magicNumber.
- Create an if-else loop with the if condition calling the first namespace with LamborghiniCar::output() if the input is 1. Otherwise, the second namespace is called similarly when the input is 2.
- If neither of these conditions are met, we print a message asking them to enter a number between 1 and 2.
Note
The solution for this activity can be found on page 285.
- Advanced Quantitative Finance with C++
- 工程軟件開發技術基礎
- Ray分布式機器學習:利用Ray進行大模型的數據處理、訓練、推理和部署
- Python金融數據分析
- jQuery開發基礎教程
- bbPress Complete
- 一塊面包板玩轉Arduino編程
- 汽車人機交互界面整合設計
- Instant jQuery Boilerplate for Plugins
- Learning Kotlin by building Android Applications
- jQuery從入門到精通(微課精編版)
- Java核心技術速學版(第3版)
- Vue.js項目開發實戰
- C++程序設計習題與實驗指導
- Python從入門到項目實踐(超值版)