我在库中找到了以下代码:
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;
};
我在库中找到了以下代码:
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;
};
这是非虚拟接口惯用语(NVI)。Herb Sutter 的那页有很多关于它的细节。但是,请使用 C++ FAQ Lite在这里和这里所说的内容来调整您在那里阅读的内容。
NVI 的主要优点是将接口与实现分离。基类可以实现通用算法并将其呈现给世界,而其子类可以通过虚函数实现算法的细节。外部用户不受算法细节更改的影响,尤其是当您后来决定要添加预处理和后处理代码时。
明显的缺点是您必须编写额外的代码。此外,private
虚拟功能让很多人感到困惑。许多编码人员错误地认为您不能覆盖它们。Herb Sutter 似乎喜欢private
虚拟,但恕我直言,在实践中遵循 C++ FAQ Lite 的建议并制作它们会更有效protected
。
这通常被称为由 Wolfgang Pree 创造的 Template-Hook 对(又名 Hotspot)。
请参阅此PDF、PowerPoint、HTML
像您所说的那样进行间接处理的一个原因是,通常可以/必须在方法之前设置一些东西,并且在方法调用之后进行一些清理。在子类中,您只需要提供必要的行为而无需进行设置和清理......
这是模板模式。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;
};
它比替代方法更好,即尝试记住单独调用每个子类中的公共代码。不可避免地,有人创建了一个子类但忘记调用公共代码,从而导致许多问题。
如果一个子类可以改变 foo_? 的定义,但是消费者需要一个静态函数(为了效率)?或者对于委托模式?