可能是重复的,但不容易搜索......
给出如下标题:
namespace ns1
{
class MyClass
{
void method();
};
}
我在.cpp文件中看到method()
以多种方式定义:
namespace ns1
{
void MyClass::method()
{
...
}
}
using namespace ns1;
void MyClass::method()
{
...
}
void ns1::MyClass::method()
{
...
}
有没有'正确'的方法呢?这些都是“错误的”,因为它们并不都意味着同样的事情吗?
答案 0 :(得分:43)
版本2不清楚且不易理解,因为您不知道哪个名称空间MyClass
属于哪个而且它只是不合逻辑(类函数不在同一名称空间中?)
版本1是正确的,因为它表明在命名空间中,您正在定义函数。
版本3也是正确的,因为您使用::
范围解析运算符来引用命名空间MyClass::method ()
中的ns1
。我更喜欢第3版。
见Namespaces (C++)。这是最好的方法。
答案 1 :(得分:23)
5年后,我想我会提到这一点,这看起来很好而且不邪恶
using ns1::MyClass;
void MyClass::method()
{
// ...
}
答案 2 :(得分:13)
我正在使用版本4(下面),因为它结合了版本1(resoective定义的简洁性)和版本3(最大限度地显示)的大部分优点。主要的缺点是人们不习惯它,但因为我认为它在技术上优于我不介意的替代品。
版本4:使用命名空间别名使用完全限定条件:
#include "my-header.hpp"
namespace OI = outer::inner;
void OI::Obj::method() {
...
}
在我的世界中,我经常使用命名空间别名,因为一切都是显式限定的 - 除非它不能(例如变量名)或它是一个已知的自定义点(例如函数模板中的swap())。
答案 3 :(得分:4)
版本3使得类和命名空间之间的关联非常明确,代价是更多的输入。版本1避免了这种情况,但捕获了与块的关联。版本2倾向于隐藏这个,所以我避免使用它。
答案 4 :(得分:3)
事实证明,它不仅仅是“编码风格的问题”。民。 2在头文件中定义和初始化声明为extern的变量时会导致链接错误。看看我的问题中的例子。 Definition of constant within namespace in cpp file
答案 5 :(得分:3)
Googles C++ Style Guide决定你的版本1,但没有缩进。
答案 6 :(得分:2)
所有方式都是正确的,每种方式都有其优点和缺点。
在版本1中,您的优势在于无需在每个函数前面编写命名空间。缺点是你会得到一个无聊的标识,特别是如果你有多个命名空间级别。
在版本2中,您可以使代码更清晰,但如果在CPP中实现了多个名称空间,则可以直接访问另一个名称空间的函数和变量,从而使您的名称空间无效(对于该cpp文件)。 / p>
在版本3中,你必须输入更多,你的功能线可能比屏幕大,这对设计效果不利。
还有一些人使用它。它类似于第一个版本,但没有标识问题。
就是这样:
#define OPEN_NS1 namespace ns1 {
#define CLOSE_NS1 }
OPEN_NS1
void MyClass::method()
{
...
}
CLOSE_NS1
由你决定哪种情况对每种情况都更好=]
答案 7 :(得分:2)
我选择Num.3(a.k.a。详细版本)。它的输入更多,但意图对您和编译器来说都是准确的。您发布的问题实际上比现实世界更简单。在现实世界中,还有其他定义范围,而不仅仅是类成员。你的定义不仅仅是类很复杂 - 因为它们的范围永远不会重新打开(与命名空间,全局范围等不同)。
Num.1这可能会失败,除了类之外的范围 - 任何可以重新打开的东西。因此,您可以使用此方法在命名空间中声明新函数,或者您的内联最终可能会被ODR替换。对于某些定义(特别是模板特化),您将需要这个。
Num.2这非常脆弱,特别是在大型代码库中 - 随着头文件和依赖项的移动,您的程序将无法编译。
Num.3这是理想的,但要输入很多 - 你的目的是定义某些东西。这正是如此,并且编译器开始确保您没有犯错,定义与其声明不同步等。