Шаблоны и иерархия действий - PullRequest
0 голосов
/ 18 февраля 2010

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

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

2) Создайте базовый класс ButtonAction, и для каждой кнопки будет другое ButtonAction. Таким образом, класс Button принимает ButtonAction в своем конструкторе для вызова при нажатии кнопки.

Мы также рассмотрели использование указателей на функции, но не продумали это до конца.

Ответы [ 2 ]

5 голосов
/ 18 февраля 2010

Вы можете использовать boost::function<> объекты для ваших действий. Таким образом, вам не нужны никакие шаблоны, и класс кнопки становится очень гибким:

struct Button {
   typedef boost::function<void ()> action_t;
   action_t action;

   Button(const action_t &a_action) : action(a_action) {
   }

   void click() {
      action();
   }
};

Таким образом, класс легко использовать с указателями на функции, объектами-функторами или такими вещами, как boost :: bind :

void dosomething();
Button b1 = Button(&dosomething);

struct SomeAction {
   void operator()() {}
};
Button b2 = Button(SomeAction());
1 голос
/ 18 февраля 2010

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

Если опция шаблона может (преждевременно беспокоиться?) Раздувать объектный код, то альтернатива полиморфизма может сделать исходный код излишне сложным.

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

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

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

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

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

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