Answers:
命名空间本质上是软件包。它们可以这样使用:
namespace MyNamespace
{
class MyClass
{
};
}
然后在代码中:
MyNamespace::MyClass* pClass = new MyNamespace::MyClass();
或者,如果您希望始终使用特定的名称空间,则可以执行以下操作:
using namespace MyNamespace;
MyClass* pClass = new MyClass();
编辑:按照bernhardrusch所说,我倾向于完全不使用“使用命名空间x”语法,我通常在实例化对象时明确指定命名空间(即,我显示的第一个示例)。
并按下面的要求,您可以使用任意数量的名称空间。
std
,但是当您处理较小的库时,我个人发现这没那么重要。通常,您只能使用using namespace FooBario;
,尤其是当您使用库中大量的类型时。
using namespace X;
应尽可能避免在头文件中使用。
mylibrary::endl
代表我自己的特殊换行序列之外,我永远不会使用其他任何东西。我的意思是,为什么要发明名称?
为了避免说出一切,Mark Ingram已经说了一些使用命名空间的提示:
避免在头文件中使用“使用名称空间”指令-这将为导入该头文件的程序的所有部分打开名称空间。在实现文件(* .cpp)中,这通常不是什么大问题-尽管我更喜欢在功能级别上使用“ using namespace”指令。
我认为名称空间主要用于避免命名冲突-不一定要组织代码结构。我主要用头文件/文件结构来组织C ++程序。
有时,较大的C ++项目中使用名称空间来隐藏实现细节。
using指令的附加说明:有些人更喜欢仅对单个元素使用“ using”:
using std::cout;
using std::endl;
using std::cout;
是使用声明
using std::cout, std::endl;
using std::cout, endl;
using namespace x
如果标头位于另一个名称空间中,则可以在标头中使用。我一般不建议这样做,但它不会污染全局名称空间。
文森特·罗伯特(Vincent Robert)的评论正确无误,您如何在C ++中正确使用名称空间?。
至少使用命名空间来避免名称冲突。在Java中,这是通过“ org.domain”惯用语强制执行的(因为它假定除了自己的域名之外,不会使用其他任何东西)。
在C ++中,可以为模块中的所有代码提供名称空间。例如,对于模块MyModule.dll,可以为其代码命名空间MyModule。我在其他地方看到有人在使用MyCompany :: MyProject :: MyModule。我想这太过分了,但总的来说,对我来说似乎是正确的。
使用时应格外小心,因为它可以将一个(或所有)符号从一个名称空间有效地导入您当前的名称空间。
在头文件中执行此操作是很邪恶的,因为您的头会污染包括它的每个源(它使我想起宏...),甚至在源文件中,函数作用域之外的样式也很糟糕,因为它将在全局作用域中导入命名空间中的符号。
使用“使用”的最安全方法是导入选择符号:
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”的信息。在教程或示例代码中。原因是减少符号数量以使阅读更容易,而不是因为它不是一个好主意。
“使用名称空间std;” 斯科特·迈耶斯(Scott Meyers)不鼓励这样做(我不记得确切是哪本书,但是如有必要,我可以找到它)。
命名空间不仅仅是包。另一个示例可以在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() ;
}
您甚至可以从不同的命名空间导入选择符号,以构建自己的自定义命名空间接口。我还没有找到实际的用法,但是从理论上讲,这很酷。
在其他答案中我没有看到任何提及,因此,这里是我的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 ns {
class A
{
};
void print(A a)
{
}
}
如果要打印一个A对象,代码将是以下代码:
ns::A a;
print(a);
请注意,在调用函数时,我们没有明确提及命名空间。这是接口原理:C ++将以类型作为参数的函数视为该类型的接口的一部分,因此无需指定名称空间,因为该参数已经隐含了名称空间。
现在为什么这个原则很重要?想象一下,类A作者没有为该类提供print()函数。您将不得不自己提供一个。作为一名优秀的程序员,您将在自己的名称空间或全局名称空间中定义此函数。
namespace ns {
class A
{
};
}
void print(A a)
{
}
您的代码可以在任何需要的地方开始调用print(a)函数。现在想象一下,几年后,作者决定提供一个优于您的print()函数,因为他知道班级的内部知识,并且可以制作出比您更好的版本。
然后,C ++作者决定应使用他的print()函数的版本,而不是另一个命名空间中提供的版本,以尊重接口原理。并且print()函数的这种“升级”应该尽可能简单,这意味着您不必更改每次对print()函数的调用。这就是为什么可以在不指定C ++中名称空间的情况下调用“接口函数”(与类在同一名称空间中的函数)的原因。
这就是为什么在使用一个C ++名称空间并牢记接口原理时应将其视为“接口”的原因。
如果您想对此行为做更好的解释,可以参考Herb Sutter的《Exceptional C ++》一书。
我见过的更大的C ++项目几乎不使用多个命名空间(例如boost库)。
实际上,boost使用了大量的名称空间,通常boost的每个部分都有自己的名称空间用于内部工作,然后可能仅将公共接口放在顶级名称空间boost中。
我个人认为,即使在单个应用程序(或库)中,代码库越大,名称空间就越重要。在工作中,我们将应用程序的每个模块放在自己的名称空间中。
我经常使用的命名空间的另一种用途(无双关)是匿名命名空间:
namespace {
const int CONSTANT = 42;
}
这基本上与以下内容相同:
static const int CONSTANT = 42;
但是,建议使用匿名名称空间(而不是静态名称空间),使代码和数据仅在C ++中的当前编译单元中可见。
const int CONSTANT = 42;
因为名称空间范围中的顶级const已经暗示了内部链接。因此,在这种情况下,您不需要匿名名称空间。
在Java中:
package somepackage;
class SomeClass {}
在C ++中:
namespace somenamespace {
class SomeClass {}
}
并使用它们,Java:
import somepackage;
和C ++:
using namespace somenamespace;
另外,全名是Java的“ somepackge.SomeClass”和C ++的“ somenamespace :: SomeClass”。使用这些约定,您可以像在Java中一样习惯进行组织,包括为名称空间创建匹配的文件夹名称。文件夹->包和文件->类要求不存在,因此您可以根据包和名称空间独立命名文件夹和类。
@ marius
是的,您可以一次使用多个名称空间,例如:
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
[2月。2014年-(真的有那么长时间吗?):这个特殊的例子现在模棱两可,正如乔伊在下面指出的那样。Boost和std :::现在每个都有一个shared_ptr。]
std
也是shared_ptr
如此,因此在尝试使用时,同时使用boost
和std
命名空间会发生冲突shared_ptr
。
std
名称空间前缀为符号,而不要使用符号using
。所以我总是写std::cout
或std::string
现在写,因为那就是我现在所说的。我永远不会只写cout
。