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

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

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

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


person Prismatic    schedule 19.03.2012    source источник
comment
Вы можете реализовать friend для интерфейсов.   -  person Matthew    schedule 19.03.2012
comment
Чистый виртуальный метод может иметь тело, и его можно вызывать явно, как base :: foo ().   -  person iammilind    schedule 19.03.2012


Ответы (2)


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

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

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; }
};
person LiquidAsh    schedule 19.03.2012
comment
Спасибо за пример. Просто для пояснения - частный чистый виртуальный никогда не может быть вызван ни одним из его потомков (но может быть реализован ими, поэтому базовый класс может вызывать метод своего потомка?) - person Prismatic; 19.03.2012
comment
Нет. В этом примере, если GrandChild вызовет foo() внутри другого из своих методов, он будет скомпилирован и будет работать должным образом, будет вызван GrandChild::foo. - person mfontanini; 19.03.2012
comment
Да Pris, виртуальная функция может быть переопределена другим типом доступа, который может сделать ее доступной. - person LiquidAsh; 19.03.2012

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

#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;
}

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

person gwshi    schedule 23.01.2013