C++详细介绍命名空间 vs 匿名 vs 私有方法到类 vs. pimpl vs. 朋友类

C++ detail namespace vs anonymous vs private method to class vs. pimpl vs. friend class

本文关键字:vs 有方法 pimpl 朋友 匿名 命名空间 C++      更新时间:2023-10-16

请耐心等待。 我试图弄清楚您在什么时候划清了将帮助程序方法放在 anon 与细节命名空间中、私有与创建 pimpl 或朋友类的界限。

这是我的看法..请让我知道你的想法。

所以,如果我有 foo.hpp 傅.cpp

我有一些自由函数bar,它们不访问foo中的任何数据成员,此外,没有客户端需要知道这些自由函数,只有foo.cpp的方法需要它们,只需直接将它们放在 foo 中的 anon 命名空间中.cpp然后完成它。

但是,如果bar需要访问foo的数据成员,我们可以制作bar私有的foo方法。但这意味着即使 foo 的客户端并不真正关心bar,每次bar更改时,我们都会重新编译。

(这部分我有点模糊): 但是,在这种情况下至少使用详细命名空间可以帮助 foo.hpp 的读者不必费心查看bar,因为他们真的不需要知道它。 这是详细命名空间约定的一般用例吗?

现在,如果我们有一堆bar_1,bar_2...bar_n,它们有点关联在一起,他们需要访问数据成员,我可以在foobaz做一个朋友类,并将bar放在那里。

但是,如果我真的担心编译时间和隐藏界面,我可以求助于 pimpl(这部分再次非常模糊,通常如果我看到这个,警铃会响起并告诉我设计中有什么问题)。

你的想法...

正如之前有人评论的那样,最好在您的问题中提供一个代码示例,因为您所描述的概念非常抽象和复杂。

以下是我对您想了解更多的项目的看法:私有方法、私有实现、未命名命名空间非成员函数、"命名"命名空间中的非成员函数和友元非成员函数。

私有方法:首先,您必须在类声明中声明这些方法,以便即使类之外没有人可以调用它,它们的原型也将公开可见。这有点无厘头。您应该在两种情况下使用这些方法:

  1. 在此方法的实现中,您需要访问类私有的内容。
  2. 您正在使用 NVI 惯用法实现虚拟方法。

私有实现:您应该使用它来隐藏类的实现详细信息。 又称其数据成员。我经常做的一件事是在我的类头文件中转发声明我的 pImpl 类型,并使我的类成为 cpp 文件中私有实现类的好友。

未命名的命名空间非成员函数:这些函数或多或少等同于在实现文件中使用 static 关键字声明的非成员函数。你应该尽可能多地为那些人拍摄。一个好的经验法则是,所有非虚拟私有方法都应该可以作为非友元、非成员函数实现,这些函数声明为 un 命名命名空间。这样做的好处是,它强制您在实现此类函数时使用类的公共接口。一个重要的警告:永远不要在头文件中使用未命名的命名空间。(.h 或 .hpp)如果这样做,则每次包含该文件时,这些文件中的每个原型都将具有唯一的符号。这可能会迅速导致符号混乱。

命名空间中的非成员非友元函数:大多数情况下,当您想要向类添加服务或提供未绑定到类的帮助程序函数时,您将使用这些函数。这些函数的优点是它们仅使用类的公共接口。正确使用这些方法的一个很好的例子是为类实现运算符时。 假设您有类"A"和类"B"。并且您希望将 A 的实例添加到 B 的实例。传递性规则说,你也可以将 B 添加到 A 中,结果相同。如果将运算符 + 设置为非成员,则无需修改任一类即可实现此功能。如果您将其作为公共方法执行,则必须在两个类中执行此操作。我会推荐你斯科特迈耶斯"有效C++"如果你想了解更多关于这个主题的信息。

好友非会员功能:应尽量避免使用此类功能。原因是它们的实现依赖于类的私人细节。不然你为什么会让他们成为朋友?可以接受的是,类的私有实现细节可以随时更改,这可能会破坏您的函数或更糟:使其行为方式与预期不同。

所以你有它,当你有虚拟方法通过 NVI 习惯用法声明时,使用 private 方法,将数据成员放在私有实现中,在未命名命名空间下的实现文件中声明所有非虚拟私有方法,尽可能将公共服务声明为非成员非友元函数,并且不使用任何友元非成员函数。