与拥有不带任何参数的私有类成员函数并直接访问成员变量相比,拥有自由函数(在匿名命名空间中并且只能在单个源文件中访问)并将所有变量作为参数发送有什么优势?
标题:
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
}
如果您更喜欢将它们设为成员,那么如果我首先调用一个不访问任何成员变量的函数,但该函数调用另一个is访问成员的函数,该怎么办?它们都应该是会员功能还是免费的?
参见这个问题:Effective C++ Item 23 优先选择非成员非友元函数而不是成员函数 还有 C++ 成员函数与自由函数
您应该更喜欢自由函数,因为它可以促进松散耦合。
仅当它在你的类的内部有效,并且你认为它确实与你的类紧密相关时,才考虑将其设为成员函数。
这是101 C++ 编码标准一书中的一个观点,它指出比起成员函数更喜欢自由函数和静态函数。
虽然这可能被认为是基于意见的,但它允许保持课堂小,并分离关注点。
这个 answer 指出:“这条规则的原因是,通过使用成员函数,您可能会意外地过度依赖类的内部结构。”
源文件中非成员函数的一个优点类似于Pimpl idiom的优点:如果您更改实现,使用您的标头的客户端不必重新编译。
// 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
的公共接口,所以你收获甚微。您可以在 friend
内放置 helper()
的 Widget
声明,但在某些时候您最好切换到成熟的 Pimpl 解决方案。
自由函数与成员函数相比的主要优点是它有助于将接口与实现解耦。例如,
std::sort
不需要知道关于它所操作的底层容器的任何事情,只需它被授予对提供某些特征的容器(通过迭代器)的访问权限即可。
在您的示例中,
DoSomething2
方法对于减少耦合没有多大作用,因为它仍然必须通过引用传递来访问私有成员。几乎可以肯定,在普通的 DoSomething
方法中进行状态突变会更明显。
当您可以根据类的公共接口实现任务或算法时,那么它就成为创建自由函数的良好候选者。 Scott Meyers 在这里总结了一套合理的规则:http://cpptips.com/nmemfunc_encap