Одним из решений было бы объявление статической защищенной функции в Base
, которая перенаправляет вызов закрытой / защищенной функции (foo
в примере).
Позволяет сказать:
class Base {
protected:
static void call_foo(Base* base) { base->foo(); }
private:
virtual void foo() = 0;
};
class Derived : public Base {
private:
Base* b;
protected:
virtual void foo(){/* Some implementation */};
virtual void foo2()
{
// b->foo(); // doesn't work
call_foo(b); // works
}
};
Таким образом, мы не нарушаем инкапсуляцию, потому что разработчик Base
может сделать явный выбор, чтобы все производные классы вызывали foo
друг на друга, избегая помещения foo
в открытый интерфейс или явно превращая все возможные подклассы Base
в друзей.
Кроме того, этот метод работает независимо от того, является ли foo
виртуальным или нет, или он является частным или защищенным.
Здесь - это ссылка на работающую версию кода выше, а здесь - еще одна версия той же идеи с чуть большей бизнес-логикой.