Существует класс
class A {
public:
A() {};
private:
void func1(int) {};
void func2(int) {};
};
Я хочу добавить указатель функции, который будет установлен в конструкторе и указывает на func1 или func2.
Таким образом, я могу назвать этот указатель (как участник класса) из каждой процедуры класса и установить этот указатель в конструкторе.
Как я могу сделать это?
class A {
public:
A(bool b) : func_ptr_(b ? &A::func1 : &A::func2) {};
void func(int i) {this->*func_ptr(i);}
private:
typedef void (A::*func_ptr_t_)();
func_ptr_t_ func_ptr_;
void func1(int) {};
void func2(int) {};
};
Учитывая это, полиморфизм может быть лучшим способом сделать все, что вы хотите сделать с этим.
Добавьте переменную-член
void (A::*ptr)();
, установите ее в конструкторе
ptr=&A::func1;
(или используйте список инициализаторов) и вызовите ее в методах A:
(this->*ptr)();
Я предлагаю вам использовать functor (или function object), а не function pointer, потому что первый безопаснее, а function pointer может быть трудным или неудобным для передачи состояния в или из функции обратного вызова
Functor - это, по сути, повторная реализация operator() класса A, для очень подробного описания, пожалуйста, обратитесь к Wikipedia: http://en.wikipedia.org/wiki/Function_object
Код должен быть примерно таким:
class A {
public:
A() {};
void operator()(int function_index, int parameter) {
if(function_index == 1)
func1(parameter);
else if(function_index == 2)
func2(parameter);
else
{ //do your other handling operation
}
}
private:
void func1( int ) {};
void func2( int) {};
};
Используя этот класс:
A a;
a(1, 123); //calling func1
a(2, 321); //calling func2
Пример ...
class A; // forward declaration
typedef void (A::*func_type)(int);
class A {
public:
A() {
func_ptr = &A::func1;
}
void test_call(int a) {
(this->*func_ptr)(a);
}
private:
func_type func_ptr;
void func1(int) {}
void func2(int) {}
};
См. boost :: function для получения информации о способе обработки указателей на функции и члены класса в более OO / C ++ манере.
Например (из документации):
struct X
{
int foo(int);
};
boost::function<int (X*, int)> f;
f = &X::foo;
X x;
f(&x, 5);
Как вы думаете, почему это плохо? Мне нужен только один указатель на функцию, и я не хочу создавать для этого два подкласса. Так почему же все так плохо?
Я скомпилировал и запустил этот код. Различные члены должны быть общедоступными, чтобы вы могли передать их в конструктор. В противном случае, пожалуйста.
Однако я согласен с другими плакатами, что это почти определенно плохой поступок. ;) Просто сделайте invoke чисто виртуальным, а затем создайте два подкласса A, каждый из которых переопределяет invoke ().
#include <iostream>
using namespace std;
class A;
typedef void(A::*MyFunc)(int) ;
class A {
public:
A() {}
A(MyFunc fp): fp(fp) {}
void invoke(int a)
{
(this->*fp)(a);
}
void func1(int a) { cout << "func1 " << a << endl; }
void func2(int a) { cout << "func2 " << a << endl; }
private:
MyFunc fp;
};
int main()
{
A* a = new A( & A::func1 );
a->invoke(5);
A* b = new A( & A::func2 );
b->invoke(6);
}