8

我在库中找到了以下代码:

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;
};
4

4 回答 4

10

是非虚拟接口惯用语(NVI)。Herb Sutter 的那页有很多关于它的细节。但是,请使用 C++ FAQ Lite在这里这里所说的内容来调整您在那里阅读的内容。

NVI 的主要优点是将接口与实现分离。基类可以实现通用算法并将其呈现给世界,而其子类可以通过虚函数实现算法的细节。外部用户不受算法细节更改的影响,尤其是当您后来决定要添加预处理和后处理代码时。

明显的缺点是您必须编写额外的代码。此外,private虚拟功能让很多人感到困惑。许多编码人员错误地认为您不能覆盖它们。Herb Sutter 似乎喜欢private虚拟,但恕我直言,在实践中遵循 C++ FAQ Lite 的建议并制作它们会更有效protected

于 2009-03-19T18:02:54.530 回答
3

这通常被称为由 Wolfgang Pree 创造的 Template-Hook 对(又名 Hotspot)。

请参阅此PDFPowerPointHTML

像您所说的那样进行间接处理的一个原因是,通常可以/必须在方法之前设置一些东西,并且在方法调用之后进行一些清理。在子类中,您只需要提供必要的行为而无需进行设置清理......

于 2009-03-19T17:54:16.033 回答
3

这是模板模式。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;
};

它比替代方法更好,即尝试记住单独调用每个子类中的公共代码。不可避免地,有人创建了一个子类但忘记调用公共代码,从而导致许多问题。

于 2009-03-19T17:58:27.273 回答
0

如果一个子类可以改变 foo_? 的定义,但是消费者需要一个静态函数(为了效率)?或者对于委托模式?

于 2009-03-19T17:55:25.953 回答