2014-09-01 40 views
1

我(希望)已经理解了私人虚拟功能的目的,但我还没有理解为什么我应该有一个私人的纯粹的虚拟功能! 我的意思是,我必须在所有派生类中定义这个函数,但这样所有对这个虚拟的调用将是对派生类中定义的调用的调用。私人纯虚拟功能的目的是什么?

假设我们有:

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

派生类基地必须定义栏(或有它的纯虚拟的,但忘了这一个时刻)。 因为Base :: bar是私有的,所以它不能被派生类使用。 由于Base是抽象的,我不能创建Base对象,因此我只能在派生类上调用foo,但这意味着Base :: bar永远不会被调用! 当然,我可以定义富:

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

但是为什么?用bar的主体定义一个非虚拟的私有函数会更好(并用它替换Base :: bar),并使纯虚拟的主体为空?

如果是这样,为什么我应该有酒吧私人(而不是保护)?我试图找到一个在互联网上的解决方案,我知道有像职位 - >C++: Private virtual functions vs. pure virtual functions,但他们帮助理解私人虚拟功能,而不是私人PURE虚拟功能。如果我错了,请原谅我!

+0

'virtual void bar()= 0 {/ * something * /}'? – ChiefTwoPencils 2014-09-01 00:03:02

+1

您不必为纯虚函数提供定义,如果这就是您要求的。 – 2014-09-01 00:08:05

+0

@ T.C。我认为你删除了我正在回应的评论。 – 2014-09-01 01:15:03

回答

1

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

是否使其成为纯虚拟取决于您的要求,有时绝对没有默认行为是有意义的,或者您希望强制所有子类实现它们自己的此虚拟功能版本。有时候一个空的实现是有意义的。然后提供,但是会发生什么情况是其他实现者可能会忘记定制他们的类,而不是实现您为其提供默认行为的虚拟类。这实际上是一个个案决定,你将不得不作出。

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

在你的问题所在的地方会有各种各样的担忧,一般使虚拟函数为私有的或受保护的,由公共函数(又称为模板方法模式)调用。如果派生类不需要调用超类实现,则将其设为私有。如果要实现默认行为,请将其保护起来并在更高级别中实施默认行为。如果你想强制子类实现它们自己的功能(独立于它们是否存在默认行为),使它成为纯虚拟的。

+0

“有些角落案例需要为纯虚函数提供实现,Herb Sutter再次列出了两个,一个提供默认行为,但强制派生类有意识地调用”,这个原因可能是有效的,如果我有这个纯粹的虚拟功能保护(或公共),但不是私人的。但是,第二个,可能是合理的:以防万一,如果有一些错误发生,我会知道,并使其私人,我不让派生类使用这种“警告”功能; .. – Toccio 2014-09-01 11:53:09

+0

..此外,使它纯粹我强加的派生实现自己的(所以“警告”纯虚拟不会被继承)。最后,我做了一个“没有主体的纯虚函数”,因为它通常不能调用(因为我没有定义它),所以避免了链接错误。 对吗? (原谅我这个长时间的回复!) – Toccio 2014-09-01 11:54:06

+0

是的,我认为你说得对,我从来没有添加过一个纯虚拟函数的实体,并且在大多数情况下,我使用带保护虚拟的模板方法。 – 2014-09-01 12:26:18

0

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

通过使bar()是纯粹的,这具有迫使可实例化的子类实现bar()或从另一个可实例化类继承的通常效果。

也许你明确不希望子类直接调用父类的酒吧(),并迫使子类来通过一些其他的保护方法,或两个间接调用它...