源文件中的私有命名空间

时间:2013-05-29 12:08:05

标签: c++ namespaces

我对私人方法有疑问功能。 假设我有一些不必在类中的实用方法。但是那些相同的方法需要调用我不想向用户公开的其他方法。例如:

Suspect.h

namespace Suspect {
  /**
  *  \brief This should do this and that and more funny things.
  */
  void VerbalKint(void);  // This is for you to use
}

Suspect.cpp

namespace Suspect {
  namespace Surprise {
    /**
    * \brief The user doesn't need to be aware of this, as long 
    *        the public available VerbalKint does what it should do.
    */
    void KeyserSoze(void) {
      // Whatever
    }
  } // end Surprise

  void VerbalKint(void) {
    Surprise::KeyserSoze();
  }
}

所以,这种布局有效。包含Suspect.h时,只有VerbalKint可见。 这可以通过使用类并将VerbalKint标记为静态来实现:

class Suspect {
public:
  // Whatever
  static void VerbalKint(void);
private:
  static void KeyserSoze(void);
};

我想知道这两种方法之间是否存在任何差异。一个比另一个更好(更快,更容易维护)吗?

你有什么想法?

4 个答案:

答案 0 :(得分:9)

最好的方法是在Suspect.cpp中的未命名命名空间中定义所有辅助函数,而不是在Suspect::Surprise命名空间中。

在您的情况下,这将是:

namespace{
void KeyserSoze(){ ... };
}

您只需在KeyserSoze内调用Suspect.cpp而无需任何名称空间说明符。

您可以在此处找到有关此内容的更多信息:Unnamed/anonymous namespaces vs. static functions

另一种方法是将KeyserSoze声明为static,但标准不建议这样做。 C ++标准在第7.3.1.1节“未命名的命名空间”中进行了介绍,第2段:

  

在声明命名空间作用域中的对象时,不推荐使用static关键字,unnamed-namespace提供了一个更好的替代方法

答案 1 :(得分:7)

如果函数是“空闲的”,则应在*.cpp中使用匿名命名空间:

namespace Suspect {
namespace Surprise {
namespace {
    void KeyserSoze(void) {
      // Whatever
    }
} // end anon
} // end Surprise
} // end Suspect

甚至:

namespace {
    void KeyserSoze(void) {
      // Whatever
    }
} // end anon

这使它远离客户端,因此在链接时他们无法访问,依赖或碰撞您的导出。如果定义可见,它还会保留不必要的声明,减少编译时间和可能的链接时间或二进制大小。最后,它使它成为私有的,因此它们不能依赖它,你不需要维护它以供它们使用。如果你选择(KeyserSoze()的情况下的函数指针),你仍然可以将它们传递给外界。

在其他时候,最好在您的类中声明一个私有成员函数,然后在*.cpp中定义它(如果可能)。通常,当您需要与班级建立更密切的关系时(例如,当您需要访问某些成员时),您会选择此方法。你说问题并非如此,但我只是重申应该使用私人成员。

答案 2 :(得分:5)

实际上,即使在未在任何标题中声明该功能时,该功能仍然不可见;如果他们写下声明,它仍然可供用户使用。

在C ++中,隐藏在文件级别声明的符号的机制是:

  • static用于(全局)变量和函数
  • namespace { ... }(匿名命名空间),用于任何你想要的东西(更一般,更详细)

例如:

// Suspect.cpp

namespace Suspect {

    static void KeyserSore() {}

    void VerbalKing() { KeyserSore(); }

}

答案 3 :(得分:2)

在类或命名空间中放置内容之间的主要区别在于,您无法在另一个头文件中的类中添加额外的静态函数。

此: A.H

namespace Fred {
   void Somefunc();
}

b.h

namespace Fred {
   void Anotherfunc();
}

工作,虽然a和b都不知道彼此对其命名空间做了什么。这可能会导致问题,例如:

c.h

namespace Fred {
   void Thirdfunc();
}

d.h

namespace Fred {
   bool Thirdfunc();
}

这一切都很好,花花公子,直到你开始运行程序......

这虽然并非不可能,但课程的可能性要小得多。

在您的示例中,只有一个源文件,您可能还需要考虑使用匿名命名空间,因为这会将声明限制为文件范围,因此文件外的人无法访问它们(或与它们发生冲突)事故。