C++ 模板与操作层次结构

C++ 模板与操作层次结构,c++,templates,C++,Templates,我正在创建一个button类,很难在两种解决方案之间做出选择 1) 模板化按钮类,并使其在按下按钮时调用构造函数中的函数对象。与我一起编写代码的人担心这会导致代码膨胀/混乱 2) 创建一个ButtonAction基类,每个按钮将有一个不同的ButtonAction。因此,按钮类在按下按钮时在其构造函数中调用一个ButtonAction 我们也考虑过函数指针的使用,但还没有仔细考虑 我会列举每种选择的后果,然后决定哪种选择最适合当前的特定情况 如果模板选项可能(过早担心?)膨胀目标代码,那么多态性

我正在创建一个button类,很难在两种解决方案之间做出选择

1) 模板化
按钮
类,并使其在按下按钮时调用构造函数中的函数对象。与我一起编写代码的人担心这会导致代码膨胀/混乱

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


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

我会列举每种选择的后果,然后决定哪种选择最适合当前的特定情况

如果模板选项可能(过早担心?)膨胀目标代码,那么多态性选项可能会使源代码变得不必要的复杂

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

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

模板替代方案允许您使用任何符合模板接口的内容。因此,如果您使用模板参数作为函数,那么您可以接受任何可以像函数一样调用的东西。这意味着你甚至不需要考虑函数指针的替代,因为模板允许你接受函数指针——而且更多。 多态性选项意味着编译器更了解您要做的事情。换句话说,模板会带来模板错误


如果您可以找到一种只使用模板
按钮
成员函数的方法,而不是使用整个
按钮
类,则可以缓解一些模板问题。将模板的实例作为函数参数,这样就不需要显式实例化模板函数。然后,您将在一些模板优势和一些多态性优势上同时获胜。

我将列举每个备选方案的结果,然后决定哪个选项最适合当前的特定情况

如果模板选项可能(过早担心?)膨胀目标代码,那么多态性选项可能会使源代码变得不必要的复杂

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

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

模板替代方案允许您使用任何符合模板接口的内容。因此,如果您使用模板参数作为函数,那么您可以接受任何可以像函数一样调用的东西。这意味着你甚至不需要考虑函数指针的替代,因为模板允许你接受函数指针——而且更多。 多态性选项意味着编译器更了解您要做的事情。换句话说,模板会带来模板错误


如果您可以找到一种只使用模板
按钮
成员函数的方法,而不是使用整个
按钮
类,则可以缓解一些模板问题。将模板的实例作为函数参数,这样就不需要显式实例化模板函数。然后,您可以在一些模板好处和一些多态性好处上同时获得这两项好处。

您可以使用
boost::function
对象执行操作。这样,您就不需要任何模板,button类变得非常灵活:

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

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

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

您可以使用
boost::function
对象执行操作。这样,您就不需要任何模板,button类变得非常灵活:

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

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

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

两者都是可以接受的解决方案。你关心什么样的标准?第二种形式可能更具可读性,但肯定更冗长。我相信你可以在没有模板的情况下实现第一个解决方案。这两个都是可以接受的解决方案。你关心什么样的标准?第二种形式可能更具可读性,但肯定更冗长。您可以在没有模板的情况下实现第一个解决方案。我相信,+ 1,也可以认为,在许多框架中,您可以将多个动作连接到一个按钮。如果您想在一点或另一点提供该功能,您只需要将内部类型更改为<代码> Boo::“信号< /代码>,并调用<代码> .Connect < /代码>,而不是将动作分配给<代码> Boo::函数< /Cord>对象+ 1,还可以考虑在许多框架中可以将多个动作连接到一个按钮。如果您想在某一点提供该功能,只需将内部类型更改为
boost::signal
并调用
.connect
,而不是将操作分配给
boost::function
对象