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(常量原子字符串&标记名,异常代码&); };
赫伯·萨特(Herb Sutter)对此做了很好的解释 指南#2:更愿意将虚拟功能私有化。 这允许派生类重写函数以自定义 在不进一步公开虚拟函数的情况下,根据需要执行操作 直接通过使它们可由派生类调用(就像 如果只是保护功能,则可能)。关键是 虚拟功能允许定制;除非他们也需要 要直接从派生类的代码中调用,没有 需要让他们做任何事,但私人的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+
如果该方法是虚拟的,那么它可以被派生类重写,即使它是私有的。调用虚拟方法时,将调用重写的版本
(与Prasoon Saurav在回答中引用的草本萨特相反,C++ FAQ Lite,主要是因为它经常混淆人)。< /P> < P>我使用它们来允许派生类在“基类”中填充“空白”,而不给最终用户暴露这样的漏洞。例如,我有一个从公共基派生的高度有状态的对象,它只能实现整个状态机的2/3(派生类根据模板参数提供剩余的1/3,而基由于其他原因不能成为模板)
至于不应该使用公共虚拟方法的论点,我说的是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++委员会放宽了“私有”,允许这种特定的访问,我将全部用于私有虚拟函数。目前,我们仍被建议在马被偷后锁上牲口棚的门看来,C++ FAQ Lite已经改变了它的建议:“C++ FAQ以前推荐使用受保护的虚拟而不是私有的虚拟。然而,私有虚拟方法现在已经足够普遍,新手的困惑就不那么令人关注了。”专家的困惑仍然是一个问题。坐在我旁边的四位C++专业人士都没有意识到私人虚拟。我认为问题是向后的。Th