未命名命名空间中的自由函数相较于具有私有成员函数的类有哪些好处?

33
在一个匿名命名空间中拥有一个自由函数并将所有变量作为参数传递,相对于拥有一个不带任何参数的私有类成员函数并直接访问成员变量,有什么优势呢?
 class A {
    int myVariable;
    void DoSomething() {
       myVariable = 1;
    }
 };

来源:

 namespace {
    void DoSomething2(int &a) {
        a = 1;
    }
 }

 int A::SomeFunction() {
    DoSomething2(myVariable); // calling free function
    DoSomething(); // calling member function
 }

如果你喜欢将它们设为成员函数,那么如果我有这样一种情况:我首先调用一个不访问任何成员变量的函数,但是这个函数又调用了另一个访问成员的函数。这两个函数应该都是成员函数还是自由函数呢?

1
你能不能至少写一些试图编译的代码? - Shoe
@StephaneRolland 不好意思,那个链接是关于公共接口的,而不是实现。 - TemplateRex
1
@TemplateRex,让我坚持一下,这是关于使用成员函数还是不使用的问题。让我引用答案说:“通过有大量直接依赖类内部的方法,最轻微的更改就意味着整个重写。这并不是必须的。” - Stephane Rolland
@StephaneRolland 您的观点很受欢迎,但它们都是指接口,而不是实现。一些好处是相同的,比如减少重新编译。 - TemplateRex
@TemplateRex 另一个好处可能是类的大小稍微更小一些。但我现在明白为什么你让我关注实现方面了。 - Stephane Rolland
3个回答

28
请看这个问题:Effective C++ Item 23 Prefer non-member non-friend functions to member functions,以及 C++ Member Functions vs Free Functions 只有在函数作用于类的内部并且与该类非常紧密相关时,您应该将其作为成员函数;否则,应优先选择自由函数,因为它会促进松散耦合。这是《101个C++编码标准》一书的观点,它建议我们在成员函数和自由函数之间优先选择自由函数和静态函数。
尽管这可能被认为是基于观点的,但它可以使类保持小巧,并将职责分离。一个回答指出:“使用成员函数的原因是,您可能会因为偶然地太过依赖类的内部而导致问题。”

成员函数的问题不是它们不能保留内部变量或指针的状态吗?我的意思是,当自由函数终止时,您在成员函数中声明的任何指针和变量也会终止... - IgorGanapolsky
3
我不确定我理解您的意思。根据我的理解,我会这样更正和重述您的句子:自由函数与方法之间没有太大差别。我们可以简化并说,方法只是有访问另一个输入参数this的能力,它是隐式传递的,并且在方法内部可访问。就局部变量和指针的生命周期范围而言,方法与自由函数的行为完全相同 - Stephane Rolland

14

在源文件中使用非成员函数的一个优点类似于Pimpl惯用法的好处:如果您更改了实现,使用您头文件的客户端无需重新编译。

// widget.h
class Widget 
{
public:
    void meh();
private:
    int bla_;
};

// widget.cpp
namespace {
    void helper(Widget* w) // clients will never know about this
    { /* yadayada */ }
}

void widget::meh() 
{ helper(this); }

当然,像这样编写的helper()只能使用Widget的公共接口,因此你获得很少的好处。你可以在Widget内部放置一个friend声明来调用helper(),但是在某些时候最好切换到完整的Pimpl解决方案。


9
自由函数与成员函数的主要优势在于它有助于将接口与实现解耦。例如,std::sort 不需要知道它所操作的底层容器的任何信息,只需要通过迭代器访问到提供某些特性的容器即可。
在您的示例中,DoSomething2 方法并没有减少耦合,因为它仍然需要通过引用传递来访问私有成员。很明显,直接在普通的 DoSomething 方法中进行状态变化更为明显。
当您可以使用类的公共接口来实现任务或算法时,就可以将其作为自由函数的好候选。Scott Meyers 在这里总结了一组合理的规则:http://cpptips.com/nmemfunc_encap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接