我有一个包含两个成员函数的类,它们共享一段代码:
void A::First()
{
firstFunctionEpilogue();
sharedPart();
}
void A::Second()
{
secondFunctionEpilogue();
sharedPart();
}
目前firstFunctionEpilogue()
,secondFunctionEpilogue()
和sharedPart()
不是函数调用,只是代码段,sharedPart()
代码是重复的。我想摆脱重复。
共享代码片段不需要访问该类的任何成员。所以我可以把它作为三个中的任何一个来实现:
哪种变体更好,为什么?
答案 0 :(得分:5)
如果您的函数访问状态但未更改它,则使用const成员函数。
您的情况:
如果你的函数1)不需要访问代码的任何成员,并且2)与该类相关,那么将它作为你的类的静态函数。
很明显,它不是修改状态,也不是基于对象的状态。
您未提及的额外案例:
还有另外一件事你也可以做。这就是让你的SharedPart接受一个成员函数指针并调用它然后处理它的主体。如果你有很多First(),Second(),Third(),Fourth(),......这样的函数,那么这可以减少代码重复。这样你就不需要继续调用SharedPart();在每个成员函数的末尾,你可以重用First(),Second(),THird(),...而无需调用代码的SharedPart()。
答案 1 :(得分:3)
我会说:
namespace beware_of_the_leopard
中。答案 2 :(得分:1)
或者它可能属于不同的类别。
或者,如果它是一个成员,它可能是虚拟的。
有很多决定,我不会过分强调它。一般来说,我选择const非静态成员函数作为默认值,除非我有充分的理由不这样做。
答案 3 :(得分:1)
将其设为非会员功能
共享代码片段不需要访问该类的任何成员。
作为一般规则,如果一段代码不需要访问该类的任何成员,则不要使其成为成员函数!尝试尽可能地封装你的类。
我建议在一个单独的命名空间中执行非成员函数,该命名空间将调用公共方法,然后调用您为共享代码创建的函数。
这是我的意思的一个例子:
namepsace Astuff{
class A{...};
void sharedPart(){...};
void first(const A& a);
void second(const A& a);
}
void Astuff::first(const A& a){
a.first();
sharedPart();
}
答案 4 :(得分:0)
一个静态成员函数,一个const 非静态成员函数或本地 功能
通常,它应该是另一个类的成员函数,或者至少是类本身的非静态成员。 如果仅从类的实例成员调用此函数 - 可能其逻辑含义需要实例,即使语法没有。除此对象之外的任何内容都可以提供有意义的参数或使用结果吗?
除非从对象实例外部调用此函数是有意义的,否则它不应该是静态的。除非在没有访问你的类的情况下调用这个函数是有意义的,否则它不应该是本地的。
借用Brian的评论中的例子: 如果此函数改变全局状态,它应该是一个全局状态类的成员; 如果此函数写入文件,则它应该是文件格式类的成员; 如果它是令人耳目一新的屏幕,它应该是......等的成员 即使它是一个简单的算术表达式,使它成为某些ArithmeticsForSpecificPurpose类的成员(静态或非静态)可能是有用的。
答案 5 :(得分:0)
使其成为非会员非朋友功能。 Scott Meyer对此here(以及Effective C ++ 3rd Edition的第23项)有一个很好的解释。
答案 6 :(得分:0)
根据经验,“尽量将其保持在本地,但必要时可以看到”。
如果调用该函数的所有代码都驻留在同一个实现文件中,这意味着将它保留在实现文件的本地。
如果你把它作为你的类的私有静态方法,它将无法通过包括你的类在内的实现来调用,但它仍然可以被它们看到。因此,每次更改该方法的语义时,包括调用在内的所有实现都必须重新编译 - 这是一个相当大的负担,因为从他们的角度来看,他们甚至不需要知道这些内容。
因此,为了最大限度地减少不必要的依赖关系,您可能希望将其设置为静态全局函数。
但是,如果您发现自己在多个实现文件中重复此全局函数,则应该将该函数移动到单独的头文件/实现文件对中,以便所有调用者都可以包含它。
无论是将该函数放置在命名空间中,还是放在全局范围内,还是作为类中的静态函数,都非常有用。
最后一点,如果你选择全局静态函数,那就是“更像c ++”的版本:匿名命名空间。它有一个很好的属性,它可以实际存储状态,也可以防止用户甚至转发声明它的任何功能。
// in your .cpp file
namespace /*anonymous*/
{
void foo()
{
// your code here
}
};
void MyClass::FooUser1() { foo(); }
void MyClass::FooUser2() { foo(); }