私有静态成员函数或匿名命名空间中的自由函数?

Eva*_*ran 34 c++ static namespaces function

我最近在风格上做了一个改变,想看看其他c ++程序员对它的看法以及是否有任何缺点.

本质上,当我需要一个不需要访问给定类成员的实用函数时,我以前做的是这样的:

file.h

class A {
public:
    // public interface
private:
    static int some_function(int);
};
Run Code Online (Sandbox Code Playgroud)

file.cpp

int A::some_function(int) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

但最近,我更喜欢做更像这样的事情:

file.cpp

namespace {
    int some_function(int) {

    }
}
// the rest of file.cpp
Run Code Online (Sandbox Code Playgroud)

这是我的思考过程:

  • 编辑的文件少了一个
  • 简单地在头文件中列出该函数可以暗示不需要公开的实现细节(即使不是公开可用的).
  • 如果函数的原型需要更改,则只需要重新编译一个文件.

最后一个对我来说是最引人注目的.所以我的问题是:这有什么缺点吗?

对于我能想到的大多数目的而言,它们在功能上是等效的.在我看来,private static函数几乎总是可以在匿名中转换为自由函数namespace.

编辑:我想到的一件事是,如果给定一个指向要操作的对象的指针,private static函数就可以访问private成员,但如果是这样的话,为什么不让它成为非static成员呢?

你们有什么感想?

Bo *_*son 23

如果该函数仅在一个源文件中使用,那么在那里定义它是完全合理的.如果没有其他人使用它,它不属于标题.

正如您所说,它减少了依赖关系并可能保存一些重新编译.

  • 当然,关键是"仅在一个源文件中使用".甚至在未命名的命名空间之前,我在这种情况下在源文件中使用`static`函数.(今天,即使在多个源中需要该函数,我也会在私有头中声明它,在私有头中,它只包含在实现文件中,而不是随库一起提供的.) (2认同)

Rob*_*b K 7

几年前我开始这样做,从未发现任何真正的退缩.对象使用的任何东西,但本身不会改变对象的状态而不需要在其他任何地方使用,我喜欢在实现文件中放入一个匿名命名空间.


spr*_*aff 5

私有静态非常量变量对于不在 .cpp 中的任何代码都是无用的,所以我总是使用这样的匿名命名空间。

静态 const 变量可能记录对客户端代码有用的约束和期望,因此它们位于标头中。

静态函数可能需要访问私有数据成员,因此如果必须的话,它们会进入标头。


Mar*_*k B 5

我看不出使用匿名名称空间的任何弊端。如果可以在不访问类成员的情况下对函数进行有用的编码,则应该这样做,因为它可以将其与类本身分离(例如,标准算法在迭代器对上的工作方式)。


Seb*_*ach 5

就个人而言,我使用的唯一静态函数是工厂函数,就像这样

class Angle {
public:
    static Angle FromDegree (float v);
    static Angle FromRadians (float v);

    ...
private:
    Angle (float degree);
};
Run Code Online (Sandbox Code Playgroud)

任何不需要私人访问的东西都是免费的.如果可能的话,任何不属于公共界面的东西都不会放在公共场所(符合您的新方法).

Scott Meyer的文章"非成员函数如何改进封装"大致描述了相同的方法:

极小和封装

在Effective C++中,我认为类接口是完整且最小的.这样的接口允许类客户端做他们可能合理想做的任何事情,但类不包含比绝对必要的更多的成员函数.我写道,添加超出让客户完成工作所需的最低限度的功能会降低类的可理解性和可维护性,并且会增加客户端的编译时间.Jack Reeves写道,除了那些真正需要的成员函数之外,它们违反了开放/封闭原则,产生了胖类接口,并最终导致软件腐烂.这是用于最小化类中成员函数数量的相当多的参数,但现在我们还有另外一个原因:如果不这样做会减少类的封装.

当然,最小类接口不一定是最好的接口.我在Effective C++中评论说,如果能够显着提高类的性能,使类更易于使用或防止可能的客户端错误,那么添加超出真正必要的功能可能是合理的.基于他对各种类似字符串的类的工作,Jack Reeves观察到一些函数在成为非成员时不会"感觉"正确,即使他们可能是非朋友的非成员.只有通过平衡许多竞争问题才能找到类的"最佳"接口,其中封装程度只有一个.

不过,这篇文章的教训应该是清楚的.尽管有传统观点,但使用非友元非成员函数可以改进类的封装,并且对成员函数的这些函数的偏好使得设计和开发具有完整且最小(或接近最小)的接口的类变得更容易.关于生成的调用语法的自然性的争论通常是没有根据的,并且对非朋友非成员函数的偏好的采用导致类的接口的打包策略,其最小化客户端编译依赖性,同时最大化它们可用的便利函数的数量.

现在是时候放弃传统但不准确的想法,即面向对象意味着什么.你是一个真正的封装信徒吗?如果是这样,我知道你会以他们应得的热情接纳非朋友的非会员职能.