私有类函数与未命名命名空间中的函数

Posted

技术标签:

【中文标题】私有类函数与未命名命名空间中的函数【英文标题】:Private class functions vs Functions in unnamed namespace 【发布时间】:2011-03-29 04:06:33 【问题描述】:

我发现自己往往没有私有类函数。如果可能的话,私有类函数的所有候选者,而不是我放入未命名的命名空间并将所有必要的信息作为函数参数传递。我没有一个合理的解释为什么我要这样做,但至少在我看来它看起来更自然。因此,我需要在头文件中公开较少的内部细节。

您的意见是什么 - 这是正确的做法吗?

【问题讨论】:

我认为这是一个非常棘手的问题 (+1)。而且我认为仍然有一些有效的答案开放...... 【参考方案1】:

在我通常工作的半大型项目(超过 200 万行代码)中,如果可以的话,我会禁止私有类函数。原因是私有类函数是私有的,但它在头文件中可见。这意味着如果我以任何方式更改签名(或评论),有时我会获得完全重新编译的奖励,这需要花费几分钟(或几个小时,具体取决于项目)。

只要拒绝并隐藏 cpp 文件中的私有内容即可。

如果我要重新开始一个大型 c++ 项目,我会强制 PIMPL Idiom: http://c2.com/cgi/wiki?PimplIdiom 将更多私人细节移到 cpp 文件中。

【讨论】:

这不是 100% 的规则。匿名命名空间有一个巨大的缺点,即无法为其中的函数编写 UT。相比之下,完全重新编译的代价可以忽略不计。就个人而言,我只是禁止匿名命名空间并强制对私有类函数进行 UT 覆盖,至少对于不太稳定的项目。 我不确定是否有谷歌。“UT”是指单元测试? 如果在单个类中更改后重新编译整个程序,您必须承担责任。 @sankalpn 你在为私有函数编写单元测试吗?我不认为这是推荐的。单元测试应该测试一个类的公共接口。如果您发现该类足够复杂以至于您想测试私有函数,那么您应该尝试将这些私有函数提取到一个新的辅助类中。然后,您可以测试帮助类的公共接口,并让原始类将一些责任委托给帮助类。如果你做得好,你会经常发现帮助类可以在代码库的其他部分重用。【参考方案2】:

我过去曾这样做过,但结果总是很糟糕。您不能将类对象传递给函数,因为它们需要访问私有成员,可能是通过引用(或者您最终得到复杂的参数列表),因此您不能调用公共类方法。出于同样的原因,您不能调用虚函数。我坚信(根据经验)这是个坏主意。

底线:这听起来像是在实现“模块”对类具有某些特殊访问权限的情况下可能可行的想法,但在 C++ 中并非如此。

【讨论】:

你是对的,有时参数列表足够大。这绝对是这种方法的缺点。另一方面,我尽量避免使用任何虚函数,所以我很少需要调用虚函数。无论如何感谢您的回答! @kriau 为什么要远离虚函数?而且您还没有消除对标头的依赖。令我震惊的是,您可能在这里寻找的是 PIMPL 成语。 像任何技术一样,很容易过度使用它。尽管如此,我已经看到了大量具有私有方法的类,它们实际上只是辅助函数。将这些从标题中移出有很多好处,并且不会受到您所描述的问题的影响。 您不一定需要访问类的私有成员。如果您需要访问,请创建一个私有方法。否则,为什么不必要地将该方法耦合到对象的内部状态? 我只在需要时才使用 PIMPL(例如为了避免在标头中包含冲突)。【参考方案3】:

这基本上归结为一个问题,即所讨论的函数作为类的一部分是否真的有意义。如果您唯一的目的是将类的详细信息保留在标题之外,我会考虑使用 pimpl 习惯用法。

【讨论】:

【参考方案4】:

我认为这是一个很好的做法。它通常还具有隐藏辅助结构和数据类型的好处,从而降低了重建的频率和大小。如果事实证明它们在其他地方有用,它还可以使这些函数更容易拆分到另一个模块中。

【讨论】:

以上是关于私有类函数与未命名命名空间中的函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能从不同命名空间中的朋友类更改类的私有成员?

使用在同一命名空间中定义的构造函数实例化命名空间中的对象。 C++

C++函数通过头文件分享给其他源文件时,使用命名空间方式,和使用类中静态函数方式,有何区别?

namespace 命名空间

PHP中命名空间是怎样的存在?

PHP之命名空间