模板与动作层次结构

时间:2010-02-18 04:04:38

标签: c++ templates

我正在创建一个按钮类,并且很难在两种解决方案之间做出决定。

1)对Button类进行模板化,并在按下按钮时在其构造函数中调用一个函数对象。我正在编码的人担心这会导致代码膨胀/颠簸。

2)创建一个ButtonAction基类,每个按钮都有一个不同的ButtonAction。因此,Button类在其构造函数中使用ButtonAction来按下按钮时调用。

我们也考虑过使用函数指针,但还没有仔细考虑过。

2 个答案:

答案 0 :(得分:5)

您可以使用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 :(得分:1)

我列举了每种方案的后果,然后决定哪种方案最适合手头的特定情况。

如果模板选项可能(过早担心?)膨胀对象代码,那么多态替代可能会使源代码变得不必要地复杂。

对于模板,编译器将为您实例化的每个函数对象创建另一个Button类。这意味着产品对象代码将比您通过子类接受各种操作对象的单个Button类更大。

在多态的情况下,编译器将生成单个Button类,但您现在将拥有另一个要维护的基类,并且您将被强制将其子类化为您添加到集合中的任何新操作。特别是,您将无法使用在创建基本操作类之前编写的操作,除非您可以修改它们,以便它们派生自该操作类。

模板替代方案允许您使用符合模板界面的任何内容。因此,如果您将模板参数用作函数,那么您可以接受任何可以像函数一样调用的内容。这意味着您甚至不需要考虑函数指针的替代方法,因为模板允许您接受函数指针 - 以及更多。

多态性选项意味着编译器会更多地了解您要执行的操作。换句话说,模板会出现模板错误。

如果您可以找到仅模板Button成员函数的方法,而不是整个Button类,则可以缓解一些模板问题。将函数参数作为模板的实例,因此您无需显式实例化模板函数。然后,您将获得一些模板优势以及一些多态性优势。