尽管有很多人呼吁将虚拟成员声明为私有的,但这个论点并不站得住脚。通常,派生类重写虚函数时需要调用基类版本,如果将其声明为private
,就无法实现:
class Base
{
private:
int m_data;
virtual void cleanup() { }
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
{
Base::cleanup();
}
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 ++委员会放宽"private"以允许这种特定访问,那么我完全支持私有虚拟函数。就目前而言,我们仍然被建议在马被偷后锁上谷仓门。