【问题标题】:Purpose of private pure virtual function?私有纯虚函数的目的?
【发布时间】:2014-10-25 04:22:54
【问题描述】:

我(希望)理解了私有虚函数的用途,但我不明白为什么我应该有一个私有的纯虚函数! 我的意思是,我必须在所有派生类中定义这个函数,但是这样所有对这个虚拟 pure 的调用都将是对派生类中定义的调用。

假设我们有:

class Base{
public:
    void foo(){ bar(); }
private:
    virtual void bar() =0 {/*something*/}
};

Base 的派生类必须定义 bar(或者让它成为纯虚拟的,但暂时忘记这一点)。 因为 Base::bar 是私有的,它不能被派生类使用。 因为 Base 是抽象的,我无法创建 Base 对象,因此我只能在派生类上调用 foo ,但这意味着永远不会调用 Base::bar ! 当然,我可以定义 foo:

void Base::foo(){
    bar();
    Base::bar();
}

但是为了什么?用bar的body定义一个非virtual private函数(并用它替换Base::bar),让pure virtual的body为空不是更好吗?

如果是这样,我为什么要设置 bar 私有(并且不受保护)?

PS:我试图在互联网上找到解决方案,我知道有类似 -> C++: Private virtual functions vs. pure virtual functions 的帖子,但它们有助于理解私有虚函数,而不是私有 PURE 虚函数。如果我错了,请原谅我!

【问题讨论】:

  • virtual void bar() =0 {/*something*/}?
  • 如果您要求的是纯虚函数,则不必提供定义。
  • @T.C.我想你删除了我正在回复的评论。
  • @NikBougalis 哦,我明白你的意思了。我在谈论“因为 Base 是抽象的,我无法创建 Base 对象,因此我只能在派生类上调用 foo”。我并不是要建议使用纯虚拟来禁用构造。
  • 私有纯虚函数在NVI(Non-Virtual Implementation)中很有用,它是模板方法模式,查看Scott Meyers的中的原则35。

标签: c++ virtual private abstract


【解决方案1】:

所以一般模式是实现公共非虚函数和私有或受保护的虚函数,看起来你已经研究过了,但这通常被称为Template Method Pattern,Herb 有更多解释萨特here 和here。

是否使其成为纯虚函数取决于您的要求,有时绝对没有有意义的默认行为,或者您想强制所有子类实现自己的此虚函数版本。有时空的实现确实有意义。然后提供,但发生的情况是其他实现者可能忘记自定义他们的类,而不是实现您为其提供默认行为的虚拟类。您必须逐案做出决定。

在某些极端情况下,您可能希望提供纯虚函数的实现,Herb Sutter again 列出了两个,一个提供默认行为但强制派生类有意识地调用,另一个是防止可能会调用纯虚函数的编译器问题。

在您的问题所在的点上存在各种问题,通常将虚拟函数设为私有或受保护,由公共函数调用(同样是模板方法模式)。如果派生类不需要调用超类实现,请将其设为私有。如果要实现默认行为,请对其进行保护并在更高的类中实现默认行为。如果您想强制子类实现自己的功能(与是否存在默认行为无关),请将其设为纯虚拟。

【讨论】:

  • "在某些极端情况下,您需要提供纯虚函数的实现,Herb Sutter 再次列出了两种,一种提供默认行为但强制派生类有意识地调用" ,如果我有这个纯虚函数受保护(或公共)但不是私有的,这个原因可能是有效的。但是,第二个可能是合理的:以防万一,如果发生一些错误,我会知道,并将其设为私有,我不让派生类使用这个“警告”功能; ..
  • .. 此外,使其纯粹我强加派生来实现自己的(所以“警告”纯虚拟不会被继承)。最后,我将“没有主体的纯虚函数”设为私有,只是因为它通常不能被调用(因为我没有定义它),避免了链接错误。我对吗? (原谅我这么长的回复!)
  • 是的,我认为你说得对,我实际上从未向纯虚函数添加主体,并且在大多数情况下,我将模板方法与受保护的虚函数一起使用。
【解决方案2】:

当然,Base 类的其他成员仍然可以调用 bar()。

通过使 bar() 成为纯函数,这具有强制可实例化子类实现 bar() 或从另一个可实例化类继承的通常效果。

也许您明确不希望子类直接调用超类的 bar(),并强制子类通过其他一些受保护的方法间接调用它,或者两个...

【讨论】:

    猜你喜欢
    • 2012-08-27
    • 2011-04-27
    • 2023-03-23
    • 2011-01-06
    • 1970-01-01
    • 2012-04-03
    • 2013-10-04
    • 2018-10-09
    相关资源
    最近更新 更多