c+命名空间
A Namespace in C++, informally, is a named scope that we can use to organize our code logically.
非正式地,C ++中的命名空间是一个命名范围,我们可以使用它在逻辑上组织我们的代码。
This will ensure that variables, functions, and classes with similar functionality are in the same scope. Not only that; it can also help avoid naming collisions since they are within a named scope.
这将确保具有相似功能的变量,函数和类在同一范围内。 不仅; 它也可以帮助避免命名冲突,因为它们在命名范围内。
Let’s look at how we can use namespaces in C++ to make our life easier.
让我们看一下如何在C ++中使用名称空间来使我们的生活更轻松。
C ++中的命名空间可以包含什么? (What can a Namespace in C++ contain?)
A namespace is just a declarative code block, which is bounded using a scope name (called the namespace name).
名称空间只是一个声明性代码块,它使用作用域名称(称为名称空间名称)限制。
Since it is a code block, it can contain variables, constants, functions, and classes. But this is a declarative code block, so you can use this only to define all your variables and classes.
由于它是一个代码块,因此可以包含变量,常量,函数和类。 但这是一个声明性代码块,因此您只能使用它来定义所有变量和类。
Let’s take an example. We’ll construct a namespace called MyNamespace
. We’ll leave it empty for now, and add stuff to it later.
让我们举个例子。 我们将构造一个名为MyNamespace
的命名空间。 我们暂时将其保留为空,然后在其中添加内容。
namespace MyNamespace {
}
This is the syntax for declaring a namespace called MyNamespace
. We can insert all of our variables, etc, within this block.
这是声明名为MyNamespace
的命名空间的语法。 我们可以在此块中插入所有变量等。
So right now, our namespace is empty. If we want to make this useful for us, let’s add some members to it!
所以现在,我们的命名空间为空。 如果我们想对我们有用,让我们添加一些成员吧!
我们如何在C ++中访问名称空间的成员? (How can we access members of a namespace in C++?)
I’ll declare a variable called my_data
, of type int, inside this namespace.
我将在此命名空间内声明一个名为int类型的变量my_data
。
namespace MyNamespace {
int my_data;
}
Whenever we declare something inside our namespace, we intend to use this from our main program later.
每当我们在命名空间中声明某些内容时,我们打算稍后在主程序中使用它。
What happens if we try to modify my_data
by trying to access it directly?
如果我们尝试通过尝试直接访问my_data
来修改my_data
,会发生什么情况?
namespace MyNamespace {
int my_data;
}
int main() {
// Try to access my_data directly will give a compilation error
my_data = 100;
return 0;
}
Output
输出量
test.cpp: In function ‘int main()’:
test.cpp:8:14: error: ‘my_data’ was not declared in this scope
my_data = 100;
^~~~~~~
test.cpp:8:14: note: suggested alternative:
test.cpp:2:13: note: ‘MyNamespace::my_data’
int my_data;
The compiler complains that it hasn’t seen a variable called my_data
in the global scope. How do we deal with this?
编译器抱怨说,它在全局范围内没有看到名为my_data
的变量。 我们该如何处理?
The answer lies in the hint that the compiler gives us!
答案就在于编译器给我们的提示!
We need to use the scope resolution operator (::
) so that our compiler can identify the scope.
我们需要使用范围解析运算符( ::
以便我们的编译器可以识别范围。
Also, this brings me to the topic of a named scope. Since our namespace has a name, the corresponding scope name will be the namespace name!
另外,这使我想到了命名范围的主题。 由于我们的名称空间具有名称,因此相应的作用域名称将是名称空间名称!
So, we combine it with the scope resolution operator to get MyNamespace::my_data
! That’s it! Now, we can do all the things we desire, since we now have access to this variable.
因此,我们将其与范围解析运算符结合在一起,以获得MyNamespace::my_data
! 而已! 现在,因为我们现在可以访问此变量,所以我们可以做所有想要的事情。
Let’s rewrite our program to use the correct scope.
让我们重写程序以使用正确的范围。
#include <iostream>
namespace MyNamespace {
int my_data;
}
int main() {
// Try to access my_data directly will give a compilation error
MyNamespace::my_data = 100;
std::cout << "Accessed MyNamespace::my_data! Assigning a value to it :" << MyNamespace::my_data << std::endl;
return 0;
}
Output
输出量
Accessed MyNamespace::my_data! Assigning a value to it : 100
Now, we’ve fixed our problem! Let’s now go to another example to show another use case of namespaces – avoiding name collision.
现在,我们已经解决了问题! 现在,让我们转到另一个示例,以显示名称空间的另一种用例–避免名称冲突。
避免函数之间的名称冲突 (Avoiding name collision between functions)
Since we mentioned that the scope of all members inside a namespace is defined by the namespace name, we can use this to avoid renaming functions.
由于我们提到了命名空间中所有成员的作用域是由命名空间名称定义的,因此我们可以使用它来避免重命名功能。
For example, in our namespace, assume that we define a function called add(x, y)
to add two numbers.
例如,在我们的命名空间中,假设我们定义了一个名为add(x, y)
的函数以将两个数字相加。
In our global scope, we can still have another separate function called add(x, y)
, or even add(x, y, z)
! This is because the scopes are different. We don’t need to unnecessarily rename functions now!
在我们的全局范围内,我们仍然可以拥有另一个名为add(x, y)
甚至add(x, y, z)
单独函数! 这是因为范围不同。 我们现在不需要不必要地重命名功能!
#include <iostream>
// Example of a Namespace:
// This is used to manage function signatures so that they don't conflict
namespace MyNamespace {
template <typename T, typename R>
auto add(T x, R y) -> decltype(x + y) {
return x + y;
}
}
// Another function called add(mul, x, y), which multiplies the result of (x + y) with mul
template <typename T, typename R>
auto add(int mul, T x, R y) -> decltype(mul * (x + y)) {
return mul * (x + y);
}
// The Main function
int main() {
std::cout << "Using MyNamespace::add() to add two types:\n";
double x = 100.5, y = 200.5;
std::cout << "Adding " << x << " and " << y << " to give " << MyNamespace::add(x, y) << std::endl;
// Adding two different types, but type compatible with addition
int a = 100;
char c = 'A';
std::cout << "Adding " << a << " and " << c << " to give " << MyNamespace::add(a, c) << std::endl;
std::cout << "Using add(mul, x, y) to add two types:\n";
std::cout << "Adding " << a << " and " << c << " to give " << add(10, a, c) << std::endl;
return 0;
}
I am using modern C++ practices in this example. Some of them are based on the Standard Template Library (STL). I am also using trailing return types, where I can specify the return type of a function after I declare its prototype.
在此示例中,我正在使用现代C ++实践。 其中一些基于标准模板库 (STL)。 我还使用尾随返回类型 ,在声明函数原型之后,可以在其中指定函数的返回类型。
Output
输出量
Using MyNamespace::add() to add two types:
Adding 100.5 and 200.5 to give 301
Adding 100 and A to give 165
Using add(mul, x, y) to add two types:
Adding 100 and A to give 1650
As you can see, we can indeed write two different functions add()
on the different scopes.
如您所见,我们确实可以在不同的作用域上编写两个不同的函数add()
。
Let’s now go to another example of namespaces, using Classes.
现在,我们使用类转到另一个名称空间示例。
在命名空间中使用类 (Using Classes inside Namespaces)
We can also use classes in our namespace. The same declaration pattern follows.
我们还可以在名称空间中使用类。 遵循相同的声明模式。
namespace MyNamespace {
// We can have functions inside a namespace
template <typename T, typename R>
auto add(T x, R y) -> decltype(x + y) {
return x + y;
}
// We can also have a Class inside a namespace
class MyClass {
public:
int a;
MyClass(int val=0) { a = val; }
~MyClass() { std::cout << "Destructor called for MyNamespace::MyClass\n"; }
};
}
Let’s write our driver program to utilize the new namespace members!
让我们编写驱动程序来利用新的名称空间成员!
#include <iostream>
// Example of a Namespace:
// This is used to manage function signatures so that they don't conflict
// Think of a namespace as a named scope binding various functions and classes
namespace MyNamespace {
// We can have functions inside a namespace
template <typename T, typename R>
auto add(T x, R y) -> decltype(x + y) {
return x + y;
}
// We can also have a Class inside a namespace
class MyClass {
public:
int a;
MyClass(int val=0) { a = val; }
~MyClass() { std::cout << "Destructor called for MyNamespace::MyClass\n"; }
};
}
// The Main function
int main() {
// Use MyClass from MyNamespace MyNamespace::MyClass
my_obj(100);
std::cout << "Created an object from MyNamespace::MyClass\n";
std::cout << "my_obj.a = " << my_obj.a << std::endl;
return 0;
}
Output
输出量
Created an object from MyNamespace::MyClass
my_obj.a = 100
Destructor called for MyNamespace::MyClass
We can also rewrite our example, by defining our Class outside the namespace, but using our scope resolution operator.
我们还可以通过在名称空间之外定义Class,但使用范围解析运算符来重写示例。
namespace MyNamespace {
// We can have functions inside a namespace
template <typename T, typename R>
auto add(T x, R y) -> decltype(x + y) {
return x + y;
}
// We can also have a Class inside a namespace
class MyClass {
public:
int a;
MyClass(int val);
~MyClass();
};
// We can define methods of the class within the namespace, but outside the class
MyClass::MyClass(int val = 0) {
MyClass::a = val;
}
}
// We can also define it outside the namespace!
MyNamespace::MyClass::~MyClass() {
std::cout << "Destructor called for MyNamespace::MyClass\n";
}
直接在C ++中访问名称空间的成员 (Accessing members of a namespace in C++ directly)
If the namespace dependency becomes long, it may be tedious and time consuming to type out the full scope of the member to access it. To overcome this, C++ introduced the using
directive.
如果名称空间依赖关系变得很长,那么键入成员的全部范围来访问它可能很繁琐且耗时。 为了克服这个问题,C ++引入了using
指令。
This will allow us to access all the names (members) in a namespace directly!
这将使我们能够直接访问名称空间中的所有名称(成员)!
We generally place this directive at the top of a file, so that it applies everywhere in the file.
我们通常将此指令放在文件的顶部,以便它适用于文件中的所有位置。
To use this, the syntax is as follows:
要使用此语法,语法如下:
using namespace namespace_name;
Where namespace_name
is your namespace name. In my case, it is MyNamespace
. So, this statement will become:
其中namespace_name
是您的名称空间名称。 就我而言,它是MyNamespace
。 因此,该语句将变为:
using namespace MyNamespace;
Now, we can directly access members inside of MyNamespace
! But keep in mind that if there is a global variable of the same name, the compiler will throw an error.
现在,我们可以直接访问MyNamespace
内的MyNamespace
! 但是请记住,如果存在同名的全局变量,则编译器将引发错误。
#include <iostream>
// Example of a Namespace:
// This is used to manage function signatures so that they don't conflict
namespace MyNamespace {
int my_data;
}
using namespace MyNamespace;
// The Main function
int main() {
// Can now access directly, provided there is no global variable of the same name!
my_data = 200;
std::cout << "my_data is now :" << my_data << std::endl;
return 0;
}
Output
输出量
my_data is now :200
结论 (Conclusion)
In this article, we learned about the concept of a namespace in C++, and how we can use them to logically organize our code. We also saw how we can use it to avoid name collisions, and also examples showing the using
directive.
在本文中,我们了解了C ++中名称空间的概念,以及如何使用它们在逻辑上组织代码。 我们还看到了如何使用它来避免名称冲突,并展示了using
指令的示例。
参考资料 (References)
- Microsoft Documentation page on the namespace in C++ (Recommended, even if you’re using Linux) C ++命名空间上的“ Microsoft文档”页面 (推荐,即使您使用的是Linux)
翻译自: https://www.journaldev.com/37681/namespace-in-c-plus-plus
c+命名空间