尽管所有调用都将虚拟成员声明为私有,但该论点根本无法成立。通常,派生类对虚拟函数的替代将必须调用基类版本。如果声明了它就不能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 ++委员会放宽“私有”以允许这种特定的访问,那么我将全部用于私有虚拟功能。就目前情况而言,仍然建议我们在马被盗后锁上谷仓门。