Чистая виртуальная функция не используется ни в одном из производных классов - PullRequest
0 голосов
/ 11 февраля 2020

Я задавал подобный вопрос ранее, но удалил его, потому что не смог придумать конкретный c пример. Я смог придумать один сейчас. Я часто нахожу себя в разработке кодов, так что виртуальные функции полезны только в некоторых, но не во всех подклассах.

Вот пример базового класса travel, который наследуется driving и flying. travel имеет функцию compute_travel_info(), которая вычисляет скорость и высоту. Первый относится как к вождению, так и к полету, а второй - только к полету.

В этом проекте driving::compute_altitude() ничего не делает, но мы должны определить его, потому что функция является чисто виртуальной (в качестве альтернативы я мог бы сделать ее виртуальной функцией в travel и определить ее, а затем не переопределить в driving). Кроме того, в идеале, я бы даже не хотел вызывать функцию compute_altitude() в compute_travel_info, если она работала с объектом driving, поэтому код может вводить в заблуждение так, как он написан.

Что я считал плохой практикой? Хмурится ли иметь виртуальную функцию, которая бесполезна в одном из подклассов, и вызывать виртуальную функцию, которая не используется в некоторых из подклассов?

Обратите внимание, что это всего лишь конкретный пример, и в идеале я хотел бы получить ответ, который применяется в целом, а не только к предоставленному примеру c. Другими словами, я не хочу, чтобы читатели были слишком зациклены на этом примере

class travel
{
  public:
       //function for representing the state in bits
   void compute_travel_info()
   {
      compute_velocity();

      compute_altitude();
   }

  private:
    double velocity;
    virtual void compute_velocity() = 0;
    virtual void compute_altitude() = 0;
};

class flying : domain
{
  void compute_velocity()
  {
    //compute the velocity
  }
  void compute_altitude()
  {
    //compute the altitude
  }    
};

class driving : travel
{
  void compute_velocity()
  {
    //compute the velocity
  }
  void compute_altitude()
  {
    //do nothing (assume car is driving on a flat earth where altitude doesn't change)
  } 
};

Ответы [ 2 ]

2 голосов
/ 11 февраля 2020

Ясно, что compute_altitude не должен быть частью вашего виртуального интерфейса, поскольку вызов его через базовый указатель не гарантирует, что он сделает что-то разумное, если он реализован как заглушка в производном классе.

Однако, compute_travel_info кажется частью виртуального интерфейса, который всегда должен вызываться через базовый указатель.

Поэтому compute_travel_info должен быть (чистым) virtual и реализован во всех производных классах. Некоторые из этих производных классов могут иметь функцию compute_altitude, которая вызывается, а некоторые - нет, но это не должно иметь значения для базового класса. Базовый класс вообще не должен иметь функцию compute_altitude.

Вы можете предоставить реализацию по умолчанию для compute_travel_info в базовом классе, которая будет переопределена только при необходимости.

Вы также можете вызовите реализацию базового класса compute_travel_info в производном классе с определенным именем (например, this->travel::compute_travel_info()), если вам нужно просто добавить к нему дополнительную работу.

Или вы можете переместить общее поведение в другое Функция базового класса, которая вызывается реализациями compute_travel_info в производных классах.

0 голосов
/ 11 февраля 2020

Вы можете добавить переопределение функции compute_travel_info в полете.

В этой переопределенной функции вы можете вызвать функцию родительского класса, которая будет содержать только функцию compute_velocity, а затем вызвать только функцию compute_altitude. в переопределенной функции.

...