我有Java背景,使用的是包,而不是名称空间。我习惯于将一起工作以形成完整对象的类放入包中,然后从该包中重用它们。但是现在我在用c++工作。
在c++中如何使用名称空间?您是为整个应用程序创建单个名称空间,还是为主要组件创建名称空间?如果是,如何从其他名称空间中的类创建对象?
我有Java背景,使用的是包,而不是名称空间。我习惯于将一起工作以形成完整对象的类放入包中,然后从该包中重用它们。但是现在我在用c++工作。
在c++中如何使用名称空间?您是为整个应用程序创建单个名称空间,还是为主要组件创建名称空间?如果是,如何从其他名称空间中的类创建对象?
当前回答
一般来说,如果我认为一段代码可能与其他库有函数或类型名称冲突,我会为它创建一个名称空间。它也有助于品牌代码,ala boost::。
其他回答
Vincent Robert在他的评论中是正确的,你如何在c++中正确使用名称空间?
使用命名空间
命名空间的使用至少有助于避免名称冲突。在Java中,这是通过“org。域名”的成语(因为它假定一个人不会使用他/她自己的域名以外的任何东西)。
在c++中,您可以为模块中的所有代码指定一个名称空间。例如,对于模块MyModule.dll,可以将其代码命名为MyModule。我在其他地方看到有人使用MyCompany::MyProject::MyModule。我想这有点过分了,但总的来说,在我看来这是正确的。
使用“使用”
Using应该非常谨慎地使用,因为它有效地将一个(或所有)符号从名称空间导入到当前名称空间。
在头文件中这样做是邪恶的,因为你的头文件会污染包括它在内的所有源代码(这让我想起了宏…),甚至在源文件中,在函数作用域之外也是糟糕的风格,因为它会在全局作用域导入命名空间中的符号。
使用"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 ;
}
您将在教程或示例代码中看到大量“使用名称空间std;”。原因是为了减少符号的数量,使阅读更容易,而不是因为这是一个好主意。
Scott Meyers不鼓励“使用命名空间std;”(我不记得具体是哪本书了,但如果有必要,我可以找到它)。
名称空间组成
名称空间不仅仅是包。另一个例子可以在Bjarne Stroustrup的“c++编程语言”中找到。
在“特别版”中,在8.2.8命名空间组合中,他描述了如何将两个命名空间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() ;
}
您甚至可以从不同的名称空间导入选择的符号,以构建您自己的自定义名称空间接口。我还没有找到它的实际用途,但在理论上,它很酷。
java和c++的另一个区别是,在c++中,名称空间层次结构不需要调整文件系统布局。因此,我倾向于将整个可重用库放在一个单独的命名空间中,并将库中的子系统放在子目录中:
#include "lib/module1.h"
#include "lib/module2.h"
lib::class1 *v = new lib::class1();
如果存在名称冲突的可能性,我只会将子系统放在嵌套的名称空间中。
我在其他答案中没有看到任何提及,所以这里是我的2美分:
在“使用名称空间”主题上,一个有用的语句是名称空间别名,允许您“重命名”名称空间,通常是给它一个更短的名称。例如,不要:
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::TheClassName foo;
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::AnotherClassName bar;
你可以这样写:
namespace Shorter = Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally;
Shorter::TheClassName foo;
Shorter::AnotherClassName bar;
另外,请注意,您可以添加到名称空间。举个例子就更清楚了,我的意思是你可以有:
namespace MyNamespace
{
double square(double x) { return x * x; }
}
在文件square.h中,和
namespace MyNamespace
{
double cube(double x) { return x * x * x; }
}
在文件cube.h中。这定义了一个单独的名称空间MyNamespace(也就是说,您可以跨多个文件定义一个单独的名称空间)。
命名空间本质上是包。它们可以这样使用:
namespace MyNamespace
{
class MyClass
{
};
}
然后在代码中:
MyNamespace::MyClass* pClass = new MyNamespace::MyClass();
或者,如果你想总是使用一个特定的名称空间,你可以这样做:
using namespace MyNamespace;
MyClass* pClass = new MyClass();
编辑:按照bernhardrusch所说,我倾向于不使用“使用名称空间x”语法,我通常在实例化对象时显式指定名称空间(即我展示的第一个示例)。
正如下面所要求的,您可以使用任意数量的名称空间。