代码之家  ›  专栏  ›  技术社区  ›  liori

为什么虚拟函数是私有的?

  •  26
  • liori  · 技术社区  · 15 年前

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

    class Foo {
    [...]
    private:
        virtual void Bar() = 0;
    [...]
    }
    

    这有什么目的吗?

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

    8 回复  |  直到 10 年前
        1
  •  22
  •   Greg Rogers    15 年前

    this Herb Sutter article 至于你为什么要做这种事。

        2
  •  10
  •   RC.    15 年前

    这是一个纯虚拟函数,恰好是私有的。这使得派生类必须实现该方法。在这种情况下,巴。

    我认为您可能会混淆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);
    };
    
    
        3
  •  9
  •   Zong    10 年前

    ISO C++ 2003明确允许:

    _§10.3未说明访问说明符,甚至在第二条中包含脚注,在虚拟函数重写的上下文中说明:

    […]访问控制(第11条)是 在确定时未考虑 压倒一切。

    该准则完全合法。

        4
  •  5
  •   Nemanja Trifunovic    15 年前

    通常的“学术”答案是:访问说明符和虚拟是正交的——一个不影响另一个。

    更实际的答案是:私有虚拟函数通常用于实现 Template Method 设计模式。在不支持私有虚拟函数的语言中,模板方法需要是公共的,尽管实际上并不打算成为接口的一部分。

        5
  •  5
  •   fredoverflow    12 年前

    我要引用伟大的 C++ FAQ Lite 总而言之:

    [23.4]什么时候应该有人使用私人 虚拟?

    几乎从来没有。

    受保护的虚拟机可以,但是 私有虚拟通常是一个网络 损失。原因:私有虚拟混淆 新C++程序员与困惑 增加成本、延误进度,以及 降低风险。

    新C++程序员迷惑 私有虚拟因为他们认为 无法重写私有虚拟。 毕竟,派生类不能 访问其中私有的成员 他们问,到底是怎么回事? 从其重写私有虚拟机 基类?有一些解释 以上,但这是学术性的。这个 真正的问题是几乎所有人 他们第一次跑的时候就迷糊了 进入私有虚拟和混乱 是坏的。

    除非有令人信服的理由 相反,避免私有虚拟。


    同时对C++ FAQ Lite进行了更新:

    顺便说一下,它混淆了大多数新手C++程序员可以重写私有虚拟,更不用说是有效的了。我们都被教导,在一个基础类中的私人成员是不可访问的,这是正确的。然而,派生类的这种不可访问性与派生类的虚拟调用机制没有任何关系。因为这可能会让新手感到困惑, C++ FAQ以前推荐使用受保护的虚拟而不是私有虚拟。然而,私有虚拟方法现在已经足够普遍了,新手的困惑就不那么令人担心了。

        6
  •  2
  •   Goz    15 年前

    它是一个纯虚拟函数。任何脱离“foo”的最终实现都必须实现“bar”功能。

        7
  •  1
  •   Rob Wells    15 年前

    它使函数成为纯虚拟的,而不是虚拟的。

    默认情况下不提供任何实现,其目的是必须由继承类指定函数实现。但是,这可以被忽略。

    有时您会看到完整的类,其中所有成员函数都以这种方式指定为纯虚拟的。

    这些是抽象的基类,有时被称为接口类,ABC的设计者对您说,“我现在已经知道如何为这个基类的所有特殊化实现这个功能。但是,你必须为你的专业工作定义所有这些,你知道你的对象应该如何表现”。

    编辑: 哎呀,刚刚发现成员纯虚拟函数是私有的。(谢谢迈克尔)这稍微改变了一点。

    当使用私有继承继承这个基类时,它会改变事情。基本上,基类的设计者所做的就是说,当派生类调用基类中的非私有函数时。部分行为已委托给派生类中的函数专业化。非私有成员正在执行“something”,“something”的一部分是通过纯虚拟基类函数调用您的实现。

    因此,foo中的一些公共函数调用foo中的bar函数,它依赖于这样一个事实,即您将为您的特定情况提供bar函数的专门实现。

    Scott Meyers将此称为“根据实施”。

    顺便说一句,只是轻声笑了笑,因为有人很快就删除了答案,但他们也没有看到问题中的“细版”!(-)

    高温高压

    干杯,

        8
  •  0
  •   Sasha    15 年前

    它的唯一目的似乎是提供一个公共接口。

    btw即使函数声明为私有虚拟,它仍然可以用类实例或从朋友那里实现和调用。

    尽管如此,这类东西通常是用来作为接口的,但我不这么做。