2010-02-18 65 views
0

我正在创建一个按钮类,并且在2个解决方案之间很难做出决定。模板与操作层次

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

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

我们也考虑过函数指针的使用,但并没有完全想到它。

+0

两个是可接受的解决方你关心什么样的标准?第二种形式可能会更可读,但肯定更罗嗦。我相信你可以在没有模板的情况下实现第一个解 – Pace 2010-02-18 04:07:08

回答

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,同样考虑到在许多框架中,您可以将多个动作连接到单个按钮。如果你想在某个点或另一个点提供该功能,只需要将你的内部类型改为'boost :: signal '并调用'.connect'而不是将该动作分配给'boost :: function <>'目的 – 2010-02-18 08:42:39

1

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

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

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

在多态性的情况下,编译器将生成一个单一的Button类,但您现在将拥有另一个基类来维护,并且您将被强制为其添加到集合的任何新操作进行子类化。特别是你不能使用在你创建基类动作类之前编写的动作,除非你可以修改它们,使它们从动作类派生。

模板替代方案允许您使用任何符合模板界面的任何东西。所以如果你使用模板参数作为函数,那么你可以接受任何可以被称为函数的东西。这意味着你甚至不需要考虑函数指针的选择,因为模板允许你接受函数指针 - 等等。

多态选项意味着编译器知道更多关于你想要做什么。换句话说,模板带有模板错误。

如果您可以找到一种方法来模板Button成员函数,而不是整个Button类,则可以缓解一些模板问题。以函数参数作为模板的一个实例,因此不需要显式实例化模板函数。然后你赢得了一些模板的好处,以及一些多态性的好处。