如何正确使用 C++ 中的命名空间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you properly use namespaces in C++?
提问by Marius
I come from a Java background, where packages are used, not namespaces. I'm used to putting classes that work together to form a complete object into packages, and then reusing them later from that package. But now I'm working in C++.
我来自 Java 背景,使用包而不是命名空间。我习惯于将一起工作以形成完整对象的类放入包中,然后稍后从该包中重用它们。但现在我正在使用 C++。
How do you use namespaces in C++? Do you create a single namespace for the entire application, or do you create namespaces for the major components? If so, how do you create objects from classes in other namespaces?
你如何在 C++ 中使用命名空间?您是为整个应用程序创建单个命名空间,还是为主要组件创建命名空间?如果是这样,您如何从其他命名空间中的类创建对象?
采纳答案by Mark Ingram
Namespaces are packages essentially. They can be used like this:
命名空间本质上是包。它们可以这样使用:
namespace MyNamespace
{
class MyClass
{
};
}
Then in code:
然后在代码中:
MyNamespace::MyClass* pClass = new MyNamespace::MyClass();
Or, if you want to always use a specific namespace, you can do this:
或者,如果您想始终使用特定的命名空间,您可以这样做:
using namespace MyNamespace;
MyClass* pClass = new MyClass();
Edit:Following what bernhardruschhas said, I tend not to use the "using namespace x" syntax at all, I usually explicitly specify the namespace when instantiating my objects (i.e. the first example I showed).
编辑:按照bernhardrusch所说的,我倾向于根本不使用“使用命名空间 x”语法,我通常在实例化对象时明确指定命名空间(即我展示的第一个示例)。
And as you asked below, you can use as many namespaces as you like.
回答by bernhardrusch
To avoid saying everything Mark Ingram already said a little tip for using namespaces:
为了避免说出所有内容,马克英格拉姆已经说过一个使用命名空间的小技巧:
Avoid the "using namespace" directive in header files - this opens the namespace for all parts of the program which import this header file. In implementation files (*.cpp) this is normally no big problem - altough I prefer to use the "using namespace" directive on the function level.
避免在头文件中使用“使用命名空间”指令 - 这会为导入此头文件的程序的所有部分打开命名空间。在实现文件 (*.cpp) 中,这通常不是大问题——尽管我更喜欢在函数级别使用“使用命名空间”指令。
I think namespaces are mostly used to avoid naming conflicts - not necessarily to organize your code structure. I'd organize C++ programs mainly with header files / the file structure.
我认为命名空间主要用于避免命名冲突 - 不一定要组织您的代码结构。我主要用头文件/文件结构来组织 C++ 程序。
Sometimes namespaces are used in bigger C++ projects to hide implementation details.
有时,在较大的 C++ 项目中使用命名空间来隐藏实现细节。
Additional note to the using directive: Some people prefer using "using" just for single elements:
using 指令的附加说明:有些人更喜欢仅对单个元素使用“using”:
using std::cout;
using std::endl;
回答by paercebal
Vincent Robert is right in his comment How do you properly use namespaces in C++?.
Vincent Robert 在他的评论中是正确的如何在 C++ 中正确使用命名空间?.
Using namespace
使用命名空间
Namespaces are used at the very least to help avoid name collision. In Java, this is enforced through the "org.domain" idiom (because it is supposed one won't use anything else than his/her own domain name).
命名空间至少用于帮助避免名称冲突。在 Java 中,这是通过“org.domain”习语强制执行的(因为假设人们不会使用他/她自己的域名之外的任何其他内容)。
In C++, you could give a namespace to all the code in your module. For example, for a module MyModule.dll, you could give its code the namespace MyModule. I've see elsewhere someone using MyCompany::MyProject::MyModule. I guess this is overkill, but all in all, it seems correct to me.
在 C++ 中,您可以为模块中的所有代码指定一个命名空间。例如,对于模块 MyModule.dll,您可以为其代码指定命名空间 MyModule。我在别处看到有人在使用 MyCompany::MyProject::MyModule。我想这有点矫枉过正,但总而言之,对我来说似乎是正确的。
Using "using"
使用“使用”
Using should be used with great care because it effectively import one (or all) symbols from a namespace into your current namespace.
Using 应该非常小心地使用,因为它可以有效地将一个(或所有)符号从命名空间导入到您当前的命名空间中。
This is evil to do it in a header file because your header will pollute every source including it (it reminds me of macros...), and even in a source file, bad style outside a function scope because it will import at global scope the symbols from the namespace.
在头文件中这样做是邪恶的,因为你的头会污染包括它的每个源(它让我想起宏......),甚至在源文件中,函数范围之外的糟糕风格,因为它将在全局范围内导入命名空间中的符号。
The most secure way to use "using" is to import select symbols:
使用“using”的最安全方法是导入选择符号:
void doSomething()
{
using std::string ; // string is now "imported", at least,
// until the end of the function
string a("Hello World!") ;
std::cout << a << std::endl ;
}
void doSomethingElse()
{
using namespace std ; // everything from std is now "imported", at least,
// until the end of the function
string a("Hello World!") ;
cout << a << endl ;
}
You'll see a lot of "using namespace std ;" in tutorial or example codes. The reason is to reduce the number of symbols to make the reading easier, not because it is a good idea.
你会看到很多“使用命名空间 std ;” 在教程或示例代码中。原因是减少符号的数量使阅读更容易,而不是因为这是一个好主意。
"using namespace std ;" is discouraged by Scott Meyers (I don't remember exactly which book, but I can find it if necessary).
“使用命名空间标准;” 被 Scott Meyers 劝阻(我不记得确切是哪本书,但如果需要我可以找到它)。
Namespace Composition
命名空间组合
Namespaces are more than packages. Another example can be found in Bjarne Stroustrup's "The C++ Programming Language".
命名空间不仅仅是包。另一个例子可以在 Bjarne Stroustrup 的“C++ 编程语言”中找到。
In the "Special Edition", at 8.2.8 Namespace Composition, he describes how you can merge two namespaces AAA and BBB into another one called CCC. Thus CCC becomes an alias for both AAA and BBB:
在“特别版”的8.2.8 Namespace Composition 中,他描述了如何将两个命名空间 AAA 和 BBB 合并为另一个名为 CCC 的命名空间。因此 CCC 成为 AAA 和 BBB 的别名:
namespace AAA
{
void doSomething() ;
}
namespace BBB
{
void doSomethingElse() ;
}
namespace CCC
{
using namespace AAA ;
using namespace BBB ;
}
void doSomethingAgain()
{
CCC::doSomething() ;
CCC::doSomethingElse() ;
}
You could even import select symbols from different namespaces, to build your own custom namespace interface. I have yet to find a practical use of this, but in theory, it is cool.
您甚至可以从不同的命名空间导入选择符号,以构建您自己的自定义命名空间接口。我还没有找到它的实际用途,但从理论上讲,它很酷。
回答by éric Malenfant
I did not see any mention of it in the other answers, so here are my 2 Canadian cents:
我在其他答案中没有看到任何提及它,所以这是我的 2 加元:
On the "using namespace" topic, a useful statement is the namespace alias, allowing you to "rename" a namespace, normally to give it a shorter name. For example, instead of:
在“使用命名空间”主题上,一个有用的声明是命名空间别名,它允许您“重命名”命名空间,通常是给它一个较短的名称。例如,而不是:
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::TheClassName foo;
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::AnotherClassName bar;
you can write:
你可以写:
namespace Shorter = Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally;
Shorter::TheClassName foo;
Shorter::AnotherClassName bar;
回答by Vincent Robert
Don't listen to every people telling you that namespaces are just name-spaces.
不要听每个人告诉你命名空间只是命名空间。
They are important because they are considered by the compiler to apply the interface principle. Basically, it can be explained by an example:
它们很重要,因为编译器认为它们应用接口原则。基本上,可以通过一个例子来解释:
namespace ns {
class A
{
};
void print(A a)
{
}
}
If you wanted to print an A object, the code would be this one:
如果你想打印一个 A 对象,代码是这样的:
ns::A a;
print(a);
Note that we didn't explicitly mention the namespace when calling the function. This is the interface principle: C++ consider a function taking a type as an argument as being part of the interface for that type, so no need to specify the namespace because the parameter already implied the namespace.
请注意,我们在调用函数时没有明确提及命名空间。这是接口原则:C++ 将一个以类型作为参数的函数视为该类型接口的一部分,因此无需指定命名空间,因为参数已经暗示了命名空间。
Now why this principle is important? Imagine that the class A author did not provide a print() function for this class. You will have to provide one yourself. As you are a good programmer, you will define this function in your own namespace, or maybe in the global namespace.
现在为什么这个原则很重要?想象一下,A 类作者没有为这个类提供 print() 函数。您必须自己提供一个。作为一名优秀的程序员,您将在自己的命名空间或全局命名空间中定义此函数。
namespace ns {
class A
{
};
}
void print(A a)
{
}
And your code can start calling the print(a) function wherever you want. Now imagine that years later, the author decides to provide a print() function, better than yours because he knows the internals of his class and can make a better version than yours.
您的代码可以在任何地方开始调用 print(a) 函数。现在想象一下,多年后,作者决定提供一个 print() 函数,它比你的更好,因为他知道他的类的内部结构,并且可以做出比你更好的版本。
Then C++ authors decided that his version of the print() function should be used instead of the one provided in another namespace, to respect the interface principle. And that this "upgrade" of the print() function should be as easy as possible, which means that you won't have to change every call to the print() function. That's why "interface functions" (function in the same namespace as a class) can be called without specifying the namespace in C++.
然后 C++ 作者决定应该使用他的 print() 函数版本而不是另一个命名空间中提供的函数,以尊重接口原则。并且 print() 函数的这种“升级”应该尽可能简单,这意味着您不必更改对 print() 函数的每次调用。这就是为什么可以在不指定 C++ 中的命名空间的情况下调用“接口函数”(与类在同一命名空间中的函数)。
And that's why you should consider a C++ namespace as an "interface" when you use one and keep in mind the interface principle.
这就是为什么在使用 C++ 命名空间时应该将 C++ 命名空间视为“接口”并牢记接口原则的原因。
If you want better explanation of this behavior, you can refer to the book Exceptional C++ from Herb Sutter
如果你想更好地解释这种行为,你可以参考Herb Sutter 的 Exceptional C++一书
回答by Vincent Robert
Bigger C++ projects I've seen hardly used more than one namespace (e.g. boost library).
我见过的更大的 C++ 项目几乎只使用了一个命名空间(例如 boost 库)。
Actually boost uses tons of namespaces, typically every part of boost has its own namespace for the inner workings and then may put only the public interface in the top-level namespace boost.
实际上 boost 使用了大量的命名空间,通常 boost 的每个部分都有自己的内部工作命名空间,然后可能只将公共接口放在顶级命名空间 boost 中。
Personally I think that the larger a code-base becomes, the more important namespaces become, even within a single application (or library). At work we put each module of our application in its own namespace.
我个人认为代码库越大,命名空间就越重要,即使在单个应用程序(或库)中也是如此。在工作中,我们将应用程序的每个模块放在自己的命名空间中。
Another use (no pun intended) of namespaces that I use a lot is the anonymous namespace:
我经常使用的命名空间的另一个用途(无双关语)是匿名命名空间:
namespace {
const int CONSTANT = 42;
}
This is basically the same as:
这与以下内容基本相同:
static const int CONSTANT = 42;
Using an anonymous namespace (instead of static) is however the recommended way for code and data to be visible only within the current compilation unit in C++.
然而,使用匿名命名空间(而不是静态命名空间)是使代码和数据仅在 C++ 中的当前编译单元内可见的推荐方式。
回答by OysterD
Also, note that you can add to a namespace. This is clearer with an example, what I mean is that you can have:
另请注意,您可以添加到命名空间。举个例子就更清楚了,我的意思是你可以有:
namespace MyNamespace
{
double square(double x) { return x * x; }
}
in a file square.h
, and
在一个文件中square.h
,和
namespace MyNamespace
{
double cube(double x) { return x * x * x; }
}
in a file cube.h
. This defines a single namespace MyNamespace
(that is, you can define a single namespace across multiple files).
在一个文件中cube.h
。这定义了单个命名空间MyNamespace
(也就是说,您可以跨多个文件定义单个命名空间)。
回答by Staale
In Java:
在 Java 中:
package somepackage;
class SomeClass {}
In C++:
在 C++ 中:
namespace somenamespace {
class SomeClass {}
}
And using them, Java:
并使用它们,Java:
import somepackage;
And C++:
和 C++:
using namespace somenamespace;
Also, full names are "somepackge.SomeClass" for Java and "somenamespace::SomeClass" for C++. Using those conventions, you can organize like you are used to in Java, including making matching folder names for namespaces. The folder->package and file->class requirements aren't there though, so you can name your folders and classes independently off packages and namespaces.
此外,Java 的全名是“somepackge.SomeClass”,C++ 的全名是“somenamespace::SomeClass”。使用这些约定,您可以像在 Java 中一样进行组织,包括为命名空间制作匹配的文件夹名称。但是文件夹-> 包和文件-> 类要求不存在,因此您可以独立于包和命名空间来命名文件夹和类。
回答by Adam Hollidge
@马吕斯
Yes, you can use several namespaces at a time, eg:
是的,您可以一次使用多个命名空间,例如:
using namespace boost;
using namespace std;
shared_ptr<int> p(new int(1)); // shared_ptr belongs to boost
cout << "cout belongs to std::" << endl; // cout and endl are in std
[Feb. 2014 -- (Has it really been that long?): This particular example is now ambiguous, as Joey points out below. Boost and std:: now each have a shared_ptr.]
[二月 2014 年——(真的有那么久吗?):这个特殊的例子现在模棱两可,正如乔伊在下面指出的那样。Boost 和 std:: 现在每个都有一个 shared_ptr。]
回答by Shadow2531
You can also contain "using namespace ..." inside a function for example:
您还可以在函数中包含“使用命名空间...”,例如:
void test(const std::string& s) {
using namespace std;
cout << s;
}