为什么虚拟功能是私有的?

lio*_*ori 26 c++ overriding virtual-functions private access-specifier

我刚刚在一些代码中发现了这个:

class Foo {
[...]
private:
    virtual void Bar() = 0;
[...]
}
Run Code Online (Sandbox Code Playgroud)

这有什么用途吗?

(我试图将一些代码从VS移植到G ++,这引起了我的注意)

Gre*_*ers 22

请参阅Herb Sutter的文章,了解为什么要做这样的事情.

  • 用你自己的话来更好地解释或总结答案.分布式自然ftw.;) (9认同)
  • 不,最好不要.我不知道Greg的教学技巧是什么样的,但我怀疑他们比Sutters更好. (8认同)
  • Herb Sutter不是最容易阅读的,所以总结会很好.但他的主题非常注重细节,所以我不知道它是可能的还是有帮助的.萨特需要一定的经验才能明白为什么他是对的. (6认同)
  • 他使用的主要理由是它将接口(公共函数)与实现(虚函数)分开.为了详细说明,你真的只是阅读了这篇文章 - 这是一个很好的阅读IMO. (3认同)
  • 所以基本上这里的重点是强制执行模板方法模式?这样派生类可以覆盖该方法,但只有基类可以调用它?我猜这很有用,但是因为派生类可以创建自己的内部方法并从Bar()调用它,所以我不确定它是否有资格作为建议. (2认同)
  • 虽然此链接可能会回答这个问题,但最好在此处包含答案的基本部分并提供参考链接.如果链接的页面发生更改,则仅链接的答案可能会无效. (2认同)

RC.*_*RC. 10

这是一个纯粹的虚拟功能,恰好是私有的.这使得派生类必须实现该方法.在这种情况下吧.

我认为你可能会感到困惑b/c这是为了在C++中创建"接口",很多时候人们都认为这些是公共的.在某些情况下,您可能希望定义一个私有接口,其中公共方法使用这些私有方法,以确保它们的调用顺序.(我相信这被称为模板方法)

对于一个相对糟糕的例子:)

class RecordFile
{
    public:
       RecordFile(const std::string &filename);

       void process(const Record &rec)
       {
           // Call the derived class function to filter out
           // records the derived instance of this class does
           // not care about
           if (filterRecord(rec))    
           {
               writeRecordToFile(rec);           
           }
       };

    private:
       // Returns true if the record is of importance
       // and should be kept
       virtual bool filterRecord(const Record &rec) = 0;

       void writeRecordToFile(const Record &rec);
};

  • Abelenky,你已经指出了关于私有虚拟的混乱的主要来源,但事实是你不必能够*调用*函数来定义*它.这让基类告诉它的后代,"给我一个函数,但我一个人就决定何时调用它." (18认同)
  • 我没有得到它,因为私有方法在派生类中不可见.派生类如何覆盖无法以任何方式"查看",调用或访问的方法? (2认同)

ova*_*nes 9

ISO C++ 2003明确允许它:

§10.3没有说明访问说明符,并且在第二个子句中包含一个脚注,在虚函数覆盖的上下文中说明:

[...]在确定覆盖时不考虑访问控制(第11条).

代码完全合法.


Ida*_*n K 5

我将从精彩的C++ FAQ Lite中引用一个简短的解释,它总结得很好:

[23.4]有人应该何时使用私人虚拟机?

几乎从不.

受保护的虚拟机是可以的,但私有虚拟机通常是净损失.原因:私有虚拟混淆了新的C++程序员,混淆会增加成本,延迟计划并降低风险.

新的C++程序员对私有虚拟机感到困惑,因为他们认为私有虚拟无法被覆盖.毕竟,派生类无法访问其基类中的私有成员,因此,他们会问,它是否可以覆盖其基类中的私有虚拟?上面有解释,但那是学术性的.真正的问题是,几乎每个人在第一次遇到私人虚拟时都会感到困惑,而且混乱也很糟糕.

除非有相反的令人信服的理由,否则请避免私人虚拟.


在此期间,C++ FAQ Lite得到了更新:

顺便说一句,它使大多数新手C++程序员感到困惑,私有虚拟可以被覆盖,更不用说有效了.我们都被告知基类中的私有成员在从它派生的类中是不可访问的,这是正确的.但是,派生类的这种不可访问性与虚拟调用机制没有任何关系,虚拟调用机制与派生类有关.由于这可能会使新手感到困惑,因此以前建议使用C++ FAQ来使用受保护的虚拟而不是私有虚拟.然而,私有虚拟方法现在足够普遍,新手的混淆不再是一个问题.

  • 这就是为什么我不喜欢C++ FAQ,它充满了有时候只是愚蠢的观点,并且违背了该领域一些主要思想家所定义的最佳实践.请参阅Herb Sutters的回答,以获得更好的解释,其中有一些不同意见. (5认同)
  • -1:许多事情使新的C++程序员感到困惑.我们是否阻止他们使用这些东西.不,当然不是因为如果我们这样做,他们会留下*新的C++程序员.什么是废话. (4认同)
  • 我认为Cline和Sutter在这里不同意.请参阅Greg Rogers的回答中的链接. (2认同)

Nem*_*vic 5

通常的"学术"答案是:访问说明符和虚拟性是正交的 - 一个不影响另一个.

更实际的答案:私有虚函数通常用于实现模板方法设计模式.在不支持私有虚函数的语言中,模板方法需要公开,尽管它并不真正意味着是接口的一部分.


Goz*_*Goz 2

它是一个纯虚函数。任何从“Foo”派生的最终实现都必须实现“Bar”函数。