domingo, 11 de março de 2012

Ponteiros para funções em c++

Ponteiros são legais, mais legal ainda são ponteiros para funções. Imagina que queremos criar uma função que encontra uma raiz de uma função em um intervalo, teremos, então, uma função que tem uma função como parâmetro.

Sua assinatura vai ser assim:
  double root(double (*f)(double), double i, double e);
O "f" é o identificador do ponteiro, do lado esquerdo fica o valor de retorno da função, e entre parênteses, do lado direito, os parâmetros. Imagina que quiséssemos um ponteiro para uma função com dois parâmetros, teríamos então:
double (*f)(double, double);
Então se quiséssemos a usar no corpo da função usaríamos, por exemplo:
 f(1.0, 5.2);
Aqui está o meu código, que acha a raíz da função x² - 1. Se quisermos usar a função root para outra função, só precisamos trocar o ponteiro.
    template <class T>
    bool eqlZero(T x) {
        return x * x < 0.000000001;
    }

    double f(double x){
        return x * x - 1.0;
    }

    // finds one root between i and e
    double root(double (*f)(double), double i, double e) {
        int iterationsLeft = 10000;
        while(iterationsLeft--) {
            double x = (i+e) / 2.0;
            cout << x << endl;
            if(eqlZero(f(x))){
                return x;
            } else if(f(x) < 0) {
                i = x;
            } else {
                e = x;
            }
        }
    }

    int _tmain(int argc, _TCHAR* argv[])
    {
        double result = root(f, -10.0, 10.0);
        cout << result;

        return 0;
    }
Esse código dá como saída o seguinte (que é quando vale a variável x a cada iteração):
0
5
2.5
1.25
0.625
0.9375
1.09375
1.01563
0.976563
0.996094
1.00586
1.00098
0.998535
0.999756
1.00037
1.00006
0.999908
0.999985
0.999985
Outra forma de implementar essa função root genérica, seria com funtores (classes com o operator ()), mas isso seria demais para esse caso. Saiba mais sobre ponteiros para funções.

Nenhum comentário:

Postar um comentário