Есть ли разница между частной и защищенной чистой виртуальной функцией?

Я могу понять, что может возникнуть причина объявить реализованную (в отличие от чистой) виртуальную функцию частной или защищенной. Afaik, если вы объявите реализованный виртуальный метод защищенным, ваш дочерний класс может вызвать метод базового класса (и никто не может). Если вы объявите его закрытым, то только базовый класс может вызвать стандартную реализацию виртуального метода.

Однако, с чистыми виртуальными системами, нет базовой реализации... Так разве это не функционально эквивалентно объявлению чистого виртуального как частного или защищенного? Защищенный чистый виртуальный интерфейс не имеет смысла, потому что вы никогда не сможете вызвать соответствующий метод базового класса. Существуют ли какие-либо сценарии, в которых защищенный чистый виртуальный смысл имеет смысл?

Есть несколько аналогичных тем на SO, но я не мог найти ничего, что бы сжато ответили на мой вопрос.

Ответ 1

Существуют ли какие-либо сценарии, в которых защищенный чистый виртуальный смысл имеет смысл?

Я думаю, что вы имеете в виду личное здесь (вместо того, чтобы защищаться), но думаю, что я понимаю вашу точку зрения. Фактически, тип доступа чистого виртуального может быть переопределен в производных классах. Вот пример, который может помочь вам увидеть разницу между приватным и защищенным чистым виртуальным:

class Parent
{
  protected: virtual void foo() = 0;
  private:   virtual void bar() = 0;
  public:            void test() { foo(); bar(); }
};

class Child : public Parent
{
  public: void test2() { foo(); /* bar(); // cannot be called here */ }
};

class GrandChild : public Child
{
  // access types here can be anything for this example
  public: void foo() { cout << "foo" << endl; }
  public: void bar() { cout << "bar" << endl; }
};

Ответ 2

Первая чистая виртуальная функция может быть реализована!

#include <iostream>

class Animal
{
public:
  void eat(void);
protected:
  virtual void doEat(void)=0;
};
void Animal::eat(void)
{
  doEat();
}
void Animal::doEat(void)
{
  std::cout << "animal" << std::endl;
}

class Tiger : public Animal
{
private:
  virtual void doEat(void)
  {
    Animal::doEat();//here is the difference between protected and private
    std::cout << "tiger" << std::endl;
  }
};

int main(void)
{
  Animal *p = new Tiger();
  p->eat();
  return 0;
}

Во-вторых, Херб Саттер объяснил, когда использовать "виртуальный частный" или "виртуальный защищенный", вы можете прочитать из этой статьи. Я думаю, это объясняет, почему мы делаем это не только мы можем! В статье говорится: "Предпочитаете делать виртуальные функции частными, Только если производным классам необходимо вызвать базовую реализацию виртуальной функции, сделайте виртуальную функцию защищенной ", ваш вопрос о чистой виртуальной функции, я не совсем уверен, удовлетворяет ли этот принцип.