2009-06-13 14 views
38
class Foo { 
public: 
    Foo() { do_something = &Foo::func_x; } 

    int (Foo::*do_something)(int); // function pointer to class member function 

    void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; } 

private: 
    int func_x(int m) { return m *= 5; } 
    int func_y(int n) { return n *= 6; } 
}; 

int 
main() 
{ 
    Foo f; 
    f.setFunc(false); 
    return (f.*do_something)(5); // <- Not ok. Compile error. 
} 

Jak mogę to uruchomić?Wskaźnik funkcji C++ (element członkowski klasy) do funkcji elementu niestacjonarnego

+1

Nie są to funkcje statyczne 'func_x' i' func_y', mimo że nie są oznaczone jako takie? –

Odpowiedz

31

Linia chcesz to

return (f.*f.do_something)(5); 

(To kompiluje - Próbowałem go)

"*f.do_something" odnosi się do samej --- wskaźnik "f" mówi nam, gdzie uzyskać wartość do_something z. Ale wciąż musimy podać obiekt, który będzie tym wskaźnikiem, gdy wywołasz tę funkcję. Dlatego potrzebujemy prefiksu "f.".

+8

Technicznie "f.do_something" zwraca wskaźnik, a operator ". *" Wywołuje funkcję wskaźnik-do-członka na klasie. –

+0

Zakładam więc, że 'return (f. * Foo :: do_something) (5)' również powinien działać. – ThomasMcLeod

+1

@ThomasMcLeod It does not. –

0

Spróbuj (f. * Do_something) (5);

35
class A{ 
    public: 
     typedef int (A::*method)(); 

     method p; 
     A(){ 
      p = &A::foo; 
      (this->*p)(); // <- trick 1, inner call 
     } 

     int foo(){ 
      printf("foo\n"); 
      return 0; 
     } 
    }; 

    void main() 
    { 
     A a; 
     (a.*a.p)(); // <- trick 2, outer call 
    } 
+3

+1 za dwie sztuczki –

+0

Tudok, po przejściu przez twoją pocztę po raz drugi uświadomiłem sobie, że podałeś właściwą odpowiedź (sztuczka 2). Dzięki. – Girish

+0

Twój kod nie działa. Kopiuję/wklejam i próbuję kompilować. test_function_pointer_2.C: W konstruktorze 'A :: A()': test_function_pointer_2.C: 7: error: argument typu 'int (A ::)()' nie pasuje 'int (A :: *)() " – user180574

-4

Myślę, że wywołanie niestatycznego elementu klasy można również wykonać przy użyciu statycznej funkcji członka.

+1

To nie jest możliwe. "Podczas modyfikowania elementu danych w deklaracji klasy słowo kluczowe static określa, że ​​jedna kopia elementu jest współużytkowana przez wszystkie instancje klasy. Podczas modyfikowania funkcji składowej w deklaracji klasy ** słowo statyczne określa, że ​​funkcja uzyskuje dostęp tylko statyczni członkowie **. " Zobacz [referencje MSDN] (http://msdn.microsoft.com/en-us/library/s1sb61xd (v = vs.80) .aspx) – ForceMagic

+0

cóż, możesz zachować listę wszystkich instancji przez konstruktora, a następnie wywołać to dla wszystkich przypadków, ale myślę, że jest to jakiś niezły pomysł: p –

3
class A { 
    int var; 
    int var2; 
public: 
    void setVar(int v); 
    int getVar(); 
    void setVar2(int v); 
    int getVar2(); 
    typedef int (A::*_fVar)(); 
    _fVar fvar; 
    void setFvar(_fVar afvar) { fvar = afvar; } 
    void insideCall() { (this->*fvar)(); } 
}; 

void A::setVar(int v) 
{ 
    var = v; 
} 

int A::getVar() 
{ 
    std::cout << "A::getVar() is called. var = " << var << std::endl; 
    return var; 
} 

void A::setVar2(int v2) 
{ 
    var2 = v2; 
} 

int A::getVar2() 
{ 
    std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl; 
    return var2; 
} 

int main() 
{ 
    A a; 
    a.setVar(3); 
    a.setVar2(5); 

// a.fvar = &A::getVar; 
    a.setFvar(&A::getVar); 
    (a.*a.fvar)(); 

    a.setFvar(&A::getVar2); 
    (a.*a.fvar)(); 

    a.setFvar(&A::getVar); 
    a.insideCall(); 

    a.setFvar(&A::getVar2); 
    a.insideCall(); 

    return 0; 
} 

Rozszerzyłem odpowiedź Nicka Dandoulakisa. Dziękuję Ci.

Dodałem funkcję, która ustawia wskaźnik funkcji członka spoza klasy. Dodałem kolejną funkcję, którą można wywołać z zewnątrz, aby pokazać wewnętrzne wywołanie wskaźnika funkcji członka.

+0

Zamiast wysyłać blok kodu, proszę * wyjaśnić, dlaczego ten kod rozwiązuje postawiony problem. Bez wyjaśnienia, to nie jest odpowiedź. –

+0

@MartijnPieters Napisałem, że został przedłużony z odpowiedzi Nicka Dandoulakisa. Zostało to wyjaśnione tam. Jestem nowy w stackoverflow, być może muszę to zrobić w inny sposób. –

+0

Cóż, możesz wyjaśnić na przykład, co zmieniłeś i dlaczego. –

0
#include<iostream> 
using namespace std; 

class A { 

public: 
    void hello() 
    { 
     cout << "hello" << endl; 
    }; 

    int x = 0; 

}; 


void main(void) 
{ 

    //pointer 
    A * a = new A; 
    void(A::*pfun)() = &A::hello; 
    int A::*v1 = &A::x; 

    (a->*pfun)(); 
    a->*v1 = 100; 
    cout << a->*v1 << endl << endl; 

    //----------------------------- 
    A b; 
    void(A::*fun)() = &A::hello; 
    int A::*v2 = &A::x; 

    (b.*fun)(); 
    b.*v2 = 200; 
    cout << b.*v2 << endl; 

} 
Powiązane problemy