一个类的友元自由函数不应该能够做到静态成员函数所能做的任何事情吗?如果是这样,为什么/何时应该优先选择静态成员函数而不是友元自由函数呢?
一般而言:
需要访问私有成员
静态成员函数可以访问类的私有成员。如果需要这样做,您可以使用静态成员函数。无论如何,在头文件中声明它以便给予访问权限,因此最好将其作为成员而不是友元函数。单例模式常常使用getInstance()方法作为静态成员函数,而使用静态工厂方法createInstance()的类则确保它们在堆上创建。这两种情况都需要访问私有构造函数。
元编程
静态成员函数非常适合模板元编程,您可以传递一个类并调用其方法,而在调用点并不知道实际调用哪个函数。这通常被称为“编译时多态”,是元编程的重要部分。std::char_traits就是基于这个原理的。
受限访问
仅为了使其仅可由类访问而使用私有静态成员函数的常见方式,而它本身不需要访问私有成员,这不是静态成员函数的良好使用,因为它是类实现细节的一部分,最好在编译单元的匿名命名空间中完成。
但是,如果静态成员函数是受保护的,那么它有用,因为它可以被派生类调用,但不可被外部类调用。
友元函数
operator<<
)dostuff< traits_class >(params);
),但这样做会更糟,因为 dostuff
不在 traits_class
范围内。 - peoro静态方法:
Animal
,而静态方法是 Create
,则必须使用 Animal::Create
来调用它。这比全局函数更好,并允许使用相对自然的语法实现工厂和 "虚构造函数"。1
,Sutter一直倡导使用非友元非成员函数,并且这与其定义相呼应,即类的公共接口由类本身以及在其头文件中提供的所有自由函数组成。 - Matthieu M.通常情况下,说实话,您不应该使用静态成员函数。免费的函数被极大地低估了。
使用静态成员(假装类只是静态成员的命名空间,这在某种程度上是正确的)获得的隐式“命名空间”是我能想到的唯一好处。
如果静态函数成员需要持久变量,则还可以使用静态数据成员。
有些人对使用静态函数持怀疑态度,因为它通常被那些来自过程化背景并不理解OO的人使用。
然而,有很多设计模式是使用静态成员函数实现的,这是有意义的。
例如,单例模式和工厂模式就是其中的两个顶级模式,实际上,大多数需要对象创建的结构模式都需要静态成员函数。
如你所说,static
成员函数没有增加任何价值。更糟糕的是,当用于实现细节时,这会引入额外的依赖关系(在编译方面)。
唯一无法使用匿名自由函数模拟的用途是protected
访问,即派生类访问父静态函数。然而,这从未是必需的:您可以将其改为常规成员函数(我假设您没有全局状态,否则静态/友元区别不是立即关注的问题)。
在模板元编程中使用static
函数已被提出...但它与内部类型问题非常相似:它使提供默认版本变得困难。另一方面,一个合适定义的自由函数(以指针形式接受类型),可以提供一个模板版本:
struct some_traits
{
static void doStuff();
};
// versus
struct some_traits {};
void doStuff(some_traits*);
// and the default: void doStuff(...);
Allocator
概念一起采取的措施:现在已经授权使用有状态的分配器,这使我们有机会将给定map
的节点打包在同一页中,而不是将它们散布在整个堆中。static
成员函数的任何好处。我希望人们能想到相反的情况来提出真正的案例。