2009-06-13 26 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. 
} 

¿Cómo puedo hacer que funcione?Puntero de función C++ (miembro de la clase) a la función miembro no estática

+1

¿No son las funciones estáticas 'func_x' y' func_y' aunque no estén marcadas como tales? –

Respuesta

31

la línea que desea es

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

(que compila - Yo lo he probado)

"*f.do_something" se refiere al propio puntero --- "f" nos dice dónde obtener el valor de do_something desde. Pero todavía tenemos que dar un objeto que será el puntero cuando llamemos a la función. Es por eso que necesitamos el prefijo "f.".

+8

Técnicamente, "f.do_something" devuelve el puntero, y el operador ". *" Llama a la función de puntero a miembro en una clase. –

+0

Supongo que 'return (f. * Foo :: do_something) (5)' también debería funcionar. – ThomasMcLeod

+1

@ThomasMcLeod No es así. –

0

Pruebe (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 por dos trucos –

+0

Tudok, después de revisar tu publicación una segunda vez, me di cuenta de que también has dado la respuesta correcta (truco 2). Gracias. – Girish

+0

Tu código no funciona. Copio/pego e intento compilar. test_function_pointer_2.C: en el constructor 'A :: A()': test_function_pointer_2.C: 7: error: el argumento de tipo 'int (A ::)()' no concuerda 'int (A :: *)() ' – user180574

-4

Creo que llamar a un miembro no estático de la clase también podría hacerse usando una función de miembro estático.

+1

Esto no es posible. "Al modificar un miembro de datos en una declaración de clase, la palabra clave static especifica que una copia del miembro es compartida por todas las instancias de la clase. Cuando se modifica una función miembro en una declaración de clase, ** la palabra clave static especifica que la función tiene acceso solo miembros estáticos **. " Consulte [Referencia de MSDN] (http://msdn.microsoft.com/en-us/library/s1sb61xd (v = vs.80) .aspx) – ForceMagic

+0

, puede guardar una lista de todas las instancias a través del constructor y luego llamar para todas las instancias, pero supongo que es una idea un tanto chocante: 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; 
} 

He extendido la respuesta de Nick Dandoulakis. Gracias.

Agregué una función que establece el puntero de la función miembro desde fuera de la clase. Agregué otra función que se puede llamar desde afuera para mostrar la llamada interna del puntero de la función miembro.

+0

En lugar de solo publicar un bloque de código, * explique * por qué este código resuelve el problema planteado. Sin una explicación, esta no es una respuesta. –

+0

@MartijnPieters Escribí que se extiende desde la respuesta de Nick Dandoulakis. Fue explicado allí. Soy nuevo en stackoverflow, quizás deba hacerlo de otra manera. –

+0

Bueno, podría explicar qué cambió, por ejemplo, y por qué. –

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; 

} 
Cuestiones relacionadas