尽管所有的调用都将虚拟成员声明为私有,但这个论点根本站不住脚。通常,派生类对虚函数的覆盖将不得不调用基类版本。如果声明它不能private
:
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) {}
};
您必须声明基类方法protected
。
然后,您必须采取丑陋的权宜之计,通过注释指示该方法应该被覆盖但不被调用。
class Base
{
...
protected:
// chained virtual function!
// call in your derived version but nowhere else.
// Use set_data instead
virtual void cleanup() { /* do something */ }
...
因此 Herb Sutter 的指导方针 #3……但无论如何,这匹马已经离开了谷仓。
当您声明某些内容时,protected
您隐含地信任任何派生类的编写者能够理解并正确使用受保护的内部结构,就像friend
声明意味着对private
成员更深的信任一样。
违反这种信任而导致不良行为的用户(例如,由于不费心阅读您的文档而被标记为“无知”)只能责怪他们自己。
更新:我收到了一些反馈,声称您可以使用私有虚拟函数以这种方式“链接”虚拟函数实现。如果是这样,我肯定想看看。
我使用的 C++ 编译器绝对不会让派生类实现调用私有基类实现。
如果 C++ 委员会放宽“私有”以允许这种特定访问,我将全力支持私有虚拟功能。就目前而言,我们仍然被建议在马被盗后锁上谷仓的门。