Вы можете сделать это, используя указатели на функции / функторы / методы. (функций должно быть достаточно и относительно просто)
Вы можете передать указатель на функцию обратного вызова в конструкторе кнопок.
Вот базовый пример использования указателей на функции.
class Button
{
typedef void(*eventFunction)();
Button( eventFunction funcPtr ) : m_funcPtr( funcPtr ){}
///< A constructor.
/// @param funcPtr The function pointer to register.
~Button(){ m_funcPtr = NULL; }
///< A destructor.
void operator() () const
{
(m_funcPtr)();
}
///< Invokes the registered function.
private:
eventFunction m_funcPtr;
};
И вы можете использовать его следующим образом:
void myFunction1() { /* do something */ }
void myFunction2() { /* do something else */ }
Button myButton1( &myFunction1 );
myButton1(); // invoke the function registered
Button myButton2( &myFunction2 );
myButton2(); // invoke the function registered
Вот более сложный пример использования шаблонов с переменным числом (C ++ 0x)
template < class Tr, class... Args >
class Button
{
typedef Tr(*eventFunction)(Args...);
Button( eventFunction funcPtr ) : m_funcPtr( funcPtr ){}
///< A constructor.
/// @param funcPtr The function pointer to register.
~Button(){ m_funcPtr = NULL; }
///< A destructor.
void operator() ( Args&... args ) const
{
(m_funcPtr)(args...);
}
///< Invokes the registered function with the provided arguments.
/// @param args The arguments to transmit to the invoked function.
private:
eventFunction m_funcPtr;
};
И вы можете использовать его следующим образом:
void myFunction1( int, double ) { /* do something */ }
void myFunction2() { /* do something */ }
Button<void, int, double> myButton1( &myFunction1 );
myButton1( 10, 20.5 ); // invoke the function registered with two arguments
Button<void> myButton2( &myFunction2 );
myButton1(); // invoke the function registered without argument
Шаблон Tr
можно удалить и заменить на void
, если вы никогда не планируете использовать другие функции, кроме функций, возвращающих void.
Таким образом Button<void, int, double> myButton1( &myFunction1 );
изменится на Button<int, double> myButton1( &myFunction1 );
и Button<void> myButton2( &myFunction2 );
изменится на Button<> myButton2( &myFunction2 );
Вы можете сделать почти то же самое с методами (вам нужно зарегистрировать указатель на экземпляр класса для вызова И указатель на метод) и с функторами (вам нужно зарегистрировать указатель на экземпляр функтора позвонить).
По вашему требованию здесь тот же класс, чтобы делать это с методами. Вам решать, как заставить ваш класс Button принимать функции, функторы и методы одновременно (подумайте виртуально ^^). Это версия C ++ 0x
template < class C, class Tr, class... Args >
class Button
{
typedef Tr(C::*eventMethod)(Args...);
~Button(){}
Button( C& target, eventMethod method ) : m_target(target), m_method(method) {}
///< A constructor.
/// @param target The class member instance used to call the method.
/// @param method The class member method pointer to register.
bool operator () ( Args&... args ) const
{
(m_target.*(m_method))(args...);
}
///< Invokes the registered method with the provided arguments.
/// @param args The arguments to transmit to the invoked method.
private:
eventMethod m_method;
C& m_target;
};
И вы можете использовать это так:
class MyClass
{
void method1(){};
void method2( int, double ){};
};
MyClass myC1;
Button<MyClass, void> myButton1( myC1, &MyClass::method1 );
myButton1(); // invoke the registered method using the registered class instance.
Button<MyClass, void, int, double> myButton2( myC1, &MyClass::method2 );
myButton2( 15, 170.5 ); // invoke the registered method using the registered class instance.
Если вам нужно вызвать его из класса, к которому принадлежит метод, используйте this
в качестве целевого параметра вместо myC1
.