2010-07-23 5 views
9

Istnieje klasaC++. metoda klasy Wskaźniki

class A { 
public: 
    A() {}; 

private: 
    void func1(int) {}; 
    void func2(int) {}; 


}; 

chcę dodać wskaźnik funkcji, które zostaną ustawione w konstruktorze i punktów func1 lub func2.

Dzięki temu mogę wywołać ten wskaźnik (jako członka klasy) z każdej procedury klasy i ustawić ten wskaźnik w konstruktorze.

Jak mogę to zrobić?

+3

W zależności od celu, wirtualne dziedziczenie lub szablon może być bardziej odpowiedni, FWIW. – Cogwheel

Odpowiedz

5

dodać zmienną członka

void (A::*ptr)(); 

ustawić go w konstruktorze

ptr=&A::func1; 

(lub skorzystać z listy initializer) i nazywają to w metodach A:

(this->*ptr)(); 
+0

(to -> * ptr)(), nie to -> * ptr() – Tomek

+0

@Tomek: Dzięki, poprawione. – jpalecek

2

Zobacz boost::function dla sposobu obsługi wskaźników funkcyjnych i elementów klasy w sposób bardziej OO/C++.

Na przykład (z dokumentacją):

struct X 
{ 
    int foo(int); 
}; 

boost::function<int (X*, int)> f; 

f = &X::foo; 

X x; 
f(&x, 5); 
0

Niektóre przykład ...

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) {} 
}; 
+0

(to -> * ptr)(), nie to -> * ptr() – Tomek

8
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) {}; 
}; 

Powiedział, polimorfizm może być lepszym sposobem, aby robić, co chcesz zrobić z tym.

+1

Zdecydowanie. Jest to podstępna i nietypowa składnia z jakiegoś powodu. Właśnie w tym problemie OO łatwo się rozwiązuje. –

+0

Kod nie kompiluje się (przynajmniej na XCode), zadeklarowałeś func_ptr_, a następnie użyłeś func_ptr ... – RelativeGames

+2

@Cippyboy: Nie jestem nawet pewien, co odpowiedzieć na to. Poszedłeś na kłopoty, by zgodzić się i komentować, ale nie naprawić tego banalnego błędu ?! Cóż, zgadnij co, zostawiam to teraz, tylko po to, żeby cię sprowokować. – sbi

2

Skompilowałem i uruchomiłem ten kod. Różni członkowie muszą być publiczni, aby móc przekazać je do konstruktora. W przeciwnym razie, proszę.

Zgadzam się jednak z innymi plakatami, że jest to zdecydowanie zła rzecz. ;) Po prostu wywołaj czysto wirtualny, a następnie wykonaj dwie podklasy A, które każda przesłonią wywołaj().

#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); 
} 
0

Dlaczego uważasz, że to źle. Potrzebuję tylko jednego wskaźnika funkcji i nie chcę tworzyć dla niego dwóch podklas. Dlaczego jest tak źle?

+0

Nie trzeba tworzyć dla niego dwóch podklas, 'A a'; jest zdefiniowanie zmiennej A i 'a (1, 123)', jest to wywołanie funkcji i wywołuje func1 z parametrem wejściowym będącym 123; wskaźnik funkcji może z pewnością obsługiwać twoje żądanie, ale funktor jest łatwiejszy w użyciu, a gramatyka jest elegancka. Kiedy ktoś potrzebuje bardziej skomplikowanych funkcji wywoływania funkcji, takich jak zapisywanie stanu, to zdecydowanie muszą korzystać z funktorów. Jeśli uważasz, że funktor może spełnić wszystkie twoje żądania, całkowicie się z tym zgadzam. Nie mam problemu, jeśli używasz C++ jako "C z klasami", ale w gruncie rzeczy C++ to znacznie więcej. – shader

1

Proponuję użyć funktor (lub obiekt funkcyjny), zamiast wskaźnika funkcji, ponieważ ta pierwsza jest bezpieczniejsze, a wskaźnik Funkcja może być trudne lub niewygodne przekazać stanu do lub z funkcji zwrotnej

A funktor jest po prostu re-implementacja operatora() z klasy A, o bardzo szczegółowym opisem Proszę odnieść się do Wikipedia: http://en.wikipedia.org/wiki/Function_object

Kod powinien być mniej więcej tak:

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) {}; 
}; 

korzystając z tej klasy:

A a; 
a(1, 123); //calling func1 
a(2, 321); //calling func2