Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C+中的私有虚方法+; PC++中的私有方法的优点是什么? 我在开源C++项目中注意到这一点: class HTMLDocument : public Document, public CachedResourceClient { private: virtual bool childAllowed(Node*); virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&); }; 类HTMLDocument:公共文档,公共缓存资源客户端{ 私人: 允许虚拟布尔子节点(节点*); 虚拟PassRefPtr createElement(常量原子字符串&标记名,异常代码&); };_C++_Polymorphism_Access Specifier - Fatal编程技术网

C+中的私有虚方法+; PC++中的私有方法的优点是什么? 我在开源C++项目中注意到这一点: class HTMLDocument : public Document, public CachedResourceClient { private: virtual bool childAllowed(Node*); virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&); }; 类HTMLDocument:公共文档,公共缓存资源客户端{ 私人: 允许虚拟布尔子节点(节点*); 虚拟PassRefPtr createElement(常量原子字符串&标记名,异常代码&); };

C+中的私有虚方法+; PC++中的私有方法的优点是什么? 我在开源C++项目中注意到这一点: class HTMLDocument : public Document, public CachedResourceClient { private: virtual bool childAllowed(Node*); virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&); }; 类HTMLDocument:公共文档,公共缓存资源客户端{ 私人: 允许虚拟布尔子节点(节点*); 虚拟PassRefPtr createElement(常量原子字符串&标记名,异常代码&); };,c++,polymorphism,access-specifier,C++,Polymorphism,Access Specifier,赫伯·萨特(Herb Sutter)对此做了很好的解释 指南#2:更愿意将虚拟功能私有化。 这允许派生类重写函数以自定义 在不进一步公开虚拟函数的情况下,根据需要执行操作 直接通过使它们可由派生类调用(就像 如果只是保护功能,则可能)。关键是 虚拟功能允许定制;除非他们也需要 要直接从派生类的代码中调用,没有 需要让他们做任何事,但私人的 如果该方法是虚拟的,那么它可以被派生类重写,即使它是私有的。调用虚拟方法时,将调用重写的版本 (与Prasoon Saurav在回答中引用的草本萨特相反,C+

赫伯·萨特(Herb Sutter)对此做了很好的解释

指南#2:更愿意将虚拟功能私有化。

这允许派生类重写函数以自定义 在不进一步公开虚拟函数的情况下,根据需要执行操作 直接通过使它们可由派生类调用(就像 如果只是保护功能,则可能)。关键是 虚拟功能允许定制;除非他们也需要 要直接从派生类的代码中调用,没有 需要让他们做任何事,但私人的


如果该方法是虚拟的,那么它可以被派生类重写,即使它是私有的。调用虚拟方法时,将调用重写的版本


(与Prasoon Saurav在回答中引用的草本萨特相反,C++ FAQ Lite,主要是因为它经常混淆人)。< /P> < P>我使用它们来允许派生类在“基类”中填充“空白”,而不给最终用户暴露这样的漏洞。例如,我有一个从公共基派生的高度有状态的对象,它只能实现整个状态机的2/3(派生类根据模板参数提供剩余的1/3,而基由于其他原因不能成为模板)

我需要有公共基类,以使许多公共API正常工作(我使用可变模板),但我不能将该对象公开。更糟糕的是,如果我将陨石坑以纯虚拟函数的形式留在状态机中,而不是“私有”的任何地方,我会允许从其子类派生的聪明或无知的用户覆盖用户永远不应该接触的方法。所以,我把状态机“大脑”放在私有虚拟函数中。然后,基类的直接子类填充其非虚拟重写的空白,用户可以安全地使用生成的对象或创建自己的进一步派生类,而不用担心弄乱状态机


至于不应该使用公共虚拟方法的论点,我说的是BS。用户可以不正确地覆盖私有虚拟对象,就像覆盖公共虚拟对象一样简单——毕竟他们正在定义新的类。如果公众不应该修改给定的API,不要让它在公共可访问的对象中成为虚拟的。

< P>我在阅读Scott Meyers的“有效C++”时首先遇到了这个概念,第35项:考虑虚拟函数的替代。我想为其他可能感兴趣的人推荐Scott Mayer

通过非虚拟接口习惯用法,它是模板方法模式的一部分:面向公众的方法不是虚拟的;相反,它们包装了私有的虚拟方法调用。然后,基类可以在私有虚拟函数调用前后运行逻辑:

public:
  void NonVirtualCalc(...)
  {
    // Setup
    PrivateVirtualCalcCall(...);
    // Clean up
  }
我认为这是一个非常有趣的设计模式,我相信您可以看到添加的控件是如何有用的

  • 为什么要将虚拟功能设置为私有?最好的理由是我们已经提供了一个面向公众的方法
  • 为什么不干脆把它设为
    受保护的
    ,这样我就可以用这个方法处理其他有趣的事情了?我想这将始终取决于您的设计以及您认为基类适合的方式。我认为派生类生成器应该专注于实现所需的逻辑;其他一切都已经处理好了。此外,还有封装的问题

从C++的角度来看,重写私有虚拟方法是完全合法的,即使您不能从类调用它。这支持上述设计。

尽管调用了所有声明虚拟成员私有的函数,但该参数根本站不住脚。通常,派生类对虚拟函数的重写必须调用基类版本。如果它被声明为私有,则不能:

class Base
{
 private:

 int m_data;

 virtual void cleanup() { /*do something*/ }

 protected:
 Base(int idata): m_data (idata) {}

 public:

 int data() const { return m_data; }
 void set_data (int ndata) { m_data = ndata; cleanup(); }
};

class Derived: public Base
{
 private:
 void cleanup() override
 {
  // do other stuff
  Base::cleanup(); // nope, can't do it
 }
 public:
 Derived (int idata): base(idata) {}
};
您必须声明基类方法
受保护

然后,您必须采取丑陋的权宜之计,通过注释指示该方法应该被重写但不被调用

class Base
{
 ...
 protected:
 // chained virtual function!
 // call in your derived version but nowhere else.
 // Use set_data instead
 virtual void cleanup() { /* do something */ }
 ...
因此赫伯·萨特的指导方针是#3#····························无论如何,马

当您声明某个
protected
时,您隐含地信任任何派生类的编写者理解并正确使用受保护的内部结构,就像
friend
声明意味着对
private
成员的更深层次信任一样

由于违反信任而导致不良行为的用户(例如,由于懒得阅读您的文档而被标记为“无知”)只能怪他们自己

更新:我收到一些反馈,声称可以使用私有虚拟函数以这种方式“链接”虚拟函数实现。如果是的话,我当然想看看

< >我使用的C++编译器绝对不会让派生类实现调用私有基类实现。
<>如果C++委员会放宽了“私有”,允许这种特定的访问,我将全部用于私有虚拟函数。目前,我们仍被建议在马被偷后锁上牲口棚的门