在.cpp文件中定义C ++命名空间方法的正确方法

时间:2011-12-30 16:37:29

标签: c++ coding-style namespaces

可能是重复的,但不容易搜索......

给出如下标题:

namespace ns1
{
 class MyClass
 {
  void method();
 };
}

我在.cpp文件中看到method()以多种方式定义:

版本1:

namespace ns1
{
 void MyClass::method()
 {
  ...
 }
}

版本2:

using namespace ns1;

void MyClass::method()
{
 ...
}

版本3:

void ns1::MyClass::method()
{
 ...
}

有没有'正确'的方法呢?这些都是“错误的”,因为它们并不都意味着同样的事情吗?

8 个答案:

答案 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,但没有缩进。

Googles C++ Style Guide for namespaces

答案 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这是理想的,但要输入很多 - 你的目的是定义某些东西。这正是如此,并且编译器开始确保您没有犯错,定义与其声明不同步等。