2010-03-08 22 views
53

Me gustaría configurar un puntero de función como miembro de una clase que sea un puntero a otra función en la misma clase. Las razones por las que estoy haciendo esto son complicadas.Puntero de función a función de miembro

En este ejemplo, me gustaría que la salida sea "1"

class A { 
public: 
int f(); 
int (*x)(); 
} 

int A::f() { 
return 1; 
} 


int main() { 
A a; 
a.x = a.f; 
printf("%d\n",a.x()) 
} 

Pero esto falla al compilar. ¿Por qué?

Respuesta

89

La sintaxis es incorrecta. Un puntero de miembro es una categoría de tipo diferente de un puntero ordinario. El puntero miembro tendrá que ser utilizado junto con un objeto de su clase:

class A { 
public: 
int f(); 
int (A::*x)(); // <- declare by saying what class it is a pointer to 
}; 

int A::f() { 
return 1; 
} 


int main() { 
A a; 
a.x = &A::f; // use the :: syntax 
printf("%d\n",(a.*(a.x))()); // use together with an object of its class 
} 

a.x sin embargo, no dice en qué objeto es la función que se llamará sucesivamente. Simplemente dice que desea utilizar el puntero almacenado en el objeto a. El antecedente a en otro momento como el operando izquierdo del operador .* le indicará al compilador en qué objeto invocar la función.

+0

Sé que esto es viejo, pero no entiendo el uso de '(a. * A.x)()'. ¿Por qué '(a. * X)()' no funciona? –

+0

@gau porque x no está en el alcance –

+1

@gau he agregado parens ahora para hacerlo más claro –

8

Necesita usar un puntero a una función miembro, no solo un puntero a una función.

class A { 
    int f() { return 1; } 
public: 
    int (A::*x)(); 

    A() : x(&A::f) {} 
}; 

int main() { 
    A a; 
    std::cout << (a.*a.x)(); 
    return 0; 
} 
15

int (*x)() no es un puntero a la función de miembro. Un puntero a la función de miembro se escribe así: int (A::*x)(void) = &A::f;.

5

Call member function on string command

#include <iostream> 
#include <string> 


class A 
{ 
public: 
    void call(); 
private: 
    void printH(); 
    void command(std::string a, std::string b, void (A::*func)()); 
}; 

void A::printH() 
{ 
    std::cout<< "H\n"; 
} 

void A::call() 
{ 
    command("a","a", &A::printH); 
} 

void A::command(std::string a, std::string b, void (A::*func)()) 
{ 
    if(a == b) 
    { 
     (this->*func)(); 
    } 
} 

int main() 
{ 
    A a; 
    a.call(); 
    return 0; 
} 

Tener en cuenta las (this->*func)(); y la forma de declarar el puntero de función con el nombre de la clase void (A::*func)()

0

Si bien esto se basa en la libra respuestas en otra parte de esta página, que tenía un caso de uso que no fue completamente resuelto por ellos; para un vector de punteros a funciones de hacer lo siguiente:

#include <iostream> 
#include <vector> 
#include <stdio.h> 
#include <stdlib.h> 

class A{ 
public: 
    typedef vector<int> (A::*AFunc)(int I1,int I2); 
    vector<AFunc> FuncList; 
    inline int Subtract(int I1,int I2){return I1-I2;}; 
    inline int Add(int I1,int I2){return I1+I2;}; 
    ... 
    void Populate(); 
    void ExecuteAll(); 
}; 

void A::Populate(){ 
    FuncList.push_back(&A::Subtract); 
    FuncList.push_back(&A::Add); 
    ... 
} 

void A::ExecuteAll(){ 
    int In1=1,In2=2,Out=0; 
    for(size_t FuncId=0;FuncId<FuncList.size();FuncId++){ 
    Out=(this->*FuncList[FuncId])(In1,In2); 
    printf("Function %ld output %d\n",FuncId,Out); 
    } 
} 

int main(){ 
    A Demo; 
    Demo.Populate(); 
    Demo.ExecuteAll(); 
    return 0; 
} 

Algo como esto es útil si usted está escribiendo un intérprete de comandos con funciones de indexado que necesitan para casarse con sintaxis de los parámetros y de ayuda consejos etc. Posiblemente también es útil en menús.

Cuestiones relacionadas