我在库中找到了以下代码:
class Bar {
public:
bool foo(int i) {
return foo_(i);
}
private:
virtual bool foo_(int i) = 0;
};
现在我想知道:你为什么要使用这个间接?可能有任何理由说明为什么上述会比简单的替代方案更好:
class Bar {
public:
virtual bool foo(int i) = 0;
};
答案 0 :(得分:10)
这是Non-Virtual Interface Idiom(NVI)。 Herb Sutter的那篇页面有很多细节。但是,使用C ++ FAQ Lite所说的here和here来调整你所阅读的内容。
NVI的主要优点是将接口与实现分离。基类可以实现通用算法并将其呈现给世界,而其子类可以通过虚函数实现算法的细节。外部用户可以避免算法细节的变化,特别是如果您以后决定要添加预处理和后处理代码。
明显的缺点是你必须编写额外的代码。此外,private
虚拟功能让很多人感到困惑。许多程序员错误地认为你无法覆盖它们。 Herb Sutter似乎喜欢虚拟private
,但恕我直言,在实践中遵循C ++ FAQ Lite的建议更有效,并使它们成为protected
。
答案 1 :(得分:3)
这通常被称为模板 - 钩子(a.k.a Hotspot),由Wolfgang Pree创造。
请参阅此PDF,PowerPoint,HTML
在调用它时执行间接的一个原因是,在方法之前通常可以/必须设置,并且有些清理 post 方法调用。在子类中,您只需提供必要的行为,而无需执行设置和清理 ......
答案 2 :(得分:2)
这是模板模式。 foo方法包含必须由所有子类执行的代码。当你这样看时,它会更有意义:
class Bar {
public:
bool foo(int i) {
// Setup / initialization / error checking / input validation etc
// that must be done for all subclasses
return foo_(i);
}
private:
virtual bool foo_(int i) = 0;
};
它比替代方案更好,它试图记住单独调用每个子类中的公共代码。不可避免地,有人会创建一个子类但忘记调用公共代码,从而导致任何数量的问题。
答案 3 :(得分:0)
如果一个子类可以改变foo_?的定义,但是消费者需要一个静态函数(为了效率)?或者代表团模式?