Статья Херба Саттера о том, как сделать виртуальные функции приватными - PullRequest
3 голосов
/ 11 февраля 2020

Я прочитал статью Херба Саттера http://www.gotw.ca/publications/mill18.htm о виртуальных функциях и о том, как они должны быть объявлены закрытыми по умолчанию. Создание виртуальной функции publi c сделает ее интерфейсом и настройщиком, и предлагается отделить интерфейс от поведения настройки, как предлагается в статье.

class shape
{
  protected:
    void set_area(double area)
    {
      area = area;
    };
  private:
    double area;
    virtual void compute_area() = 0;
};
class square
{

  private:
    double length;
    void compute_area()
    {
      set_area(length*length);
    }
};

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

class shape
{
  public:
    void interfacer()
    {
      compute_area();
    }
  protected:
    void set_area(double area)
    {
      area = area;
    };
  private:
    double area;
    virtual void compute_area() = 0;
}

Разве это не кажется излишним по сравнению с возможностью просто сделать:

shape *ptr = new square();
ptr->compute_area(); 

, если бы мы сделали виртуальную функцию доступной c?

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

1 Ответ

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

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

Вы, кажется, спрашиваете, в чем смысл этого: почему пользователи вызывают функцию publi c, которая вызывает частная реализация, а не просто одна функция, которая делает работу? Херб отвечает на это в посте:

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

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

В-третьих, базовый класс теперь меньше fr agile перед лицом изменений. Мы можем потом передумать и добавить проверку до и после условия, или разделить обработку на несколько этапов, или выполнить рефакторинг, или реализовать более полное разделение интерфейса / реализации, используя идиому Pimpl [4], или внести другие изменения в настраиваемость Widget, не затрагивая код, который использует виджет. ...

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

...