我有Java背景,使用的是包,而不是名称空间。我习惯于将一起工作以形成完整对象的类放入包中,然后从该包中重用它们。但是现在我在用c++工作。

在c++中如何使用名称空间?您是为整个应用程序创建单个名称空间,还是为主要组件创建名称空间?如果是,如何从其他名称空间中的类创建对象?


当前回答

另外,请注意,您可以添加到名称空间。举个例子就更清楚了,我的意思是你可以有:

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 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的《例外c++》这本书

@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

[2014年2月-(真的有那么长时间吗?):正如乔伊在下面指出的,这个特殊的例子现在是模棱两可的。Boost和std::现在各有一个shared_ptr.]

我更喜欢为应用程序使用顶级名称空间,而为组件使用子名称空间。

使用来自其他名称空间的类的方式与java中的方式惊人地相似。 你可以使用“use NAMESPACE”,这类似于“import PACKAGE”语句,例如使用std。或者你指定包作为类的前缀,用“::”分隔,例如std::string。这类似于“java.lang”。字符串”。

在Java中:

package somepackage;
class SomeClass {}

在c++中:

namespace somenamespace {
    class SomeClass {}
}

使用它们,Java:

import somepackage;

和c++:

using namespace somenamespace;

此外,全名是“somepackage”。用于Java的SomeClass和用于c++的somenamespace::SomeClass。使用这些约定,您可以像在Java中一样进行组织,包括为名称空间创建匹配的文件夹名称。但是没有文件夹->包和文件->类的要求,因此您可以根据包和名称空间独立地命名文件夹和类。

你也可以在函数中包含"using namespace…",例如:

void test(const std::string& s) {
    using namespace std;
    cout << s;
}