Незважаючи на всі заклики оголосити віртуального члена приватним, аргумент просто не тримає уваги. Часто перекриття похідного класу віртуальної функції доведеться викликати версію базового класу. Не може, якщо це оголошено 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 */ }
...
Таким чином, керівництво №3 Герба Саттера ... Але кінь все одно вийшов із сараю.
Коли ви декларуєте щось, protected
ви неявно довіряєте письменнику будь-якого похідного класу, щоб зрозуміти та належним чином використовувати захищені інтернали, саме так, як friend
декларація передбачає більш глибоку довіру до private
членів.
Користувачі, які мають погану поведінку в порушенні цього довіри (наприклад, позначений як "безглуздий", не намагаючись читати вашу документацію), винні лише у цьому.
Оновлення . У мене були деякі відгуки, які стверджують, що ви можете "ланцюжок" реалізацій віртуальної функції таким чином, використовуючи приватні віртуальні функції. Якщо так, я б точно хотів це побачити.
Компілятори C ++, які я використовую, точно не дозволяють реалізації похідного класу викликати реалізацію приватного базового класу.
Якби комітет C ++ розслабився "приватним", щоб дозволити цей специфічний доступ, я був би все для приватних віртуальних функцій. На сьогоднішній день нам все ж рекомендують зачинити двері сараю після того, як кінь буде викрадений.