вопросы о статье, представляющей интерфейс C ++ - PullRequest
6 голосов
/ 28 января 2010

Я читал статью об интерфейсах C ++ (http://accu.org/index.php/journals/233)), и я полностью потерян в той части, где говорится, что все виртуальные функции-члены должны быть приватными (раздел под названием «Усиление разделения»). Это просто не имеет смысла для меня вообще.

По словам автора, код выглядит так:

class shape {
public:
  virtual ~shape();
  virtual void move_x(distance x) = 0;
  virtual void move_y(distance y) = 0;
  virtual void rotate(angle rotation) = 0;
  //...
};

class line : public shape {
public:
  line(point end_point_1, point end_point_2);
  //...
private:
  virtual ~line();
  virtual void move_x(distance x);
  virtual void move_y(distance y);
  virtual void rotate(angle rotation);
  //...
};

Итак, у нас есть чисто виртуальная функция, которая является публичной, и ее реализация (в классе строки), которая является приватной.

Может кто-нибудь объяснить, как можно вызывать функцию move_x? Его спецификатор доступа является приватным, и если я попытаюсь сделать это, он приведет к ошибке:

line my_line(point(0,0), point(1,2));
my_line.move_x(-1); // does not compile

Точно так же правильно сказать, что интерфейс рисования (см. Ранее в статье) также не может получить доступ к этим функциям?

Спасибо.

Ответы [ 4 ]

6 голосов
/ 28 января 2010

Идея состоит в том, что вы будете использовать эти методы через ссылку или указатель на shape.

shape &s = my_line;
s.move_x(-1);

Это может быть оправдано на основании «раскрыть только то, что вам нужно», или как форма самодокументирования. Это доказывает, что методы вызываются только по назначению.

4 голосов
/ 28 января 2010

Если у вас есть экземпляр line объекта, у вас может возникнуть соблазн вызвать его методы. Но если единственный способ добиться этого - запросить интерфейс shape, тогда объект выглядит не так, как объект, а скорее как набор интерфейсов.

Это имеет больше смысла, если вы представляете линию, реализующую более одного интерфейса.

3 голосов
/ 28 января 2010

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

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

Дальнейшее развитие этой идеи - менее радикальное и пригодное для использования в более широком контексте - Невиртуальный интерфейс (NVI) Херба Саттера.

2 голосов
/ 28 января 2010

Я думаю, что статья хорошо объясняет обоснование в этой цитате:

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

То есть line само по себе не интересно. Это просто реализация интерфейса shape, и могут быть другие реализации. Вы особенно заинтересованы в интерфейсе shape. Следовательно, вы должны получать доступ к реализации только через этот интерфейс, а не как отдельный класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...