Newsgroup: it.comp.lang.c++
Titolo: Passaggio di puntatori a funzioni membro

Ciao a tutti, prima di scrivere questo messaggio ho tentato di leggere
quante più messaggi ed esempi possibili, ma ancora non sono giunto ad
un risultato.
In un piccolo programma che sto sviluppando ho una serie di equazioni
delle quali devo trovare gli zeri. Sono tutte equazioni del tipo y=f(x)
e sono contenute
all'interno di una classe. Le equazioni in questione sono un po' più
complicate di quelle riportate nell'esempio e devono essere risolte con
un metodo approssimato,
io uso il metodo delle secanti, nel cui codice si deve calcolare il
valore delle funzioni. Ho pensato, un ormai triste giorno, di ricorrere
ai puntatori a funzioni.
Se la mia classe è la seguente:
	class a
	{
	public:
		a();
		double f1(double val){return val*2;};
		double f2(double val){return val/2;};
	}
ed io scrivo:
	double (a::*f)(double);
	f = &a::f1;
	(this->*f)(1.2);
il codice funziona correttamente.
Come devo scrivere la funzione che realizza il metodo delle secanti?
Se scrivo questo:
double func(double (*a)(double))
{
	(*f)(1.2);
}
tutto continua a funzionare, ma non penso che sia corretta. Quando
cerco di richiamarla passandogli il puntatore alla funzione in questo
modo:
	func(this->*func);
mi da il seguente errore:
[c:\...] : error C2664: 'func' : cannot convert parameter 1 from
'overloaded function type' to 'double (__cdecl *)(double)'
Grazie per l'aiuto.

 	func(this->*func);
Non puoi presentarci del codice completamente fuori dal contesto.
Non conviene usare i puntatori se non sono indispensabili.
Se proprio vuoi, dovrai fare qualcosa del genere:
#include <iostream>
class A
{
public:
	double f1(double val) { return val*2; }
	double f2(double val) { return val/2; }
};
class B
{
public:
	double g1(double val) { return val; }
	double g2(double val) { return val-1.0; }
};
template <class T>
double secant(T& t, double (T::*f)(double))
{
	return (t.*f)(2.3);
}
int main()
{
	A a;
	B b;
	std::cout << secant(a, &A::f1) << std::endl;
	std::cout << secant(b, &B::g2) << std::endl;
}
Kiuhnm

La funzione secante deve essere richiamata da un'altra funzione membro
della classe a.
Grazie per l'aiuto.

 della classe a.
Divertiti:
#include <iostream>
class A
{
	double f1(double val) { return val*2; }
	double f2(double val) { return val/2; }
	static double (A::*p[])(double);
	double secant(double (A::*f)(double))
	{
		return (this->*f)(2.3);
	}
public:
	double call(unsigned index)
	{
		if (index >= 2)
			throw;
		return secant(p[index]);
	}
};
double (A::*A::p[])(double) = {&A::f1, &A::f2};
int main()
{
	A a;
	std::cout << a.call(0) << std::endl;
	std::cout << a.call(1) << std::endl;
}
Kiuhnm

Era meglio se scrivevi "impazzisci" :-)
Mi piaceva più la versione di prima, era più leggibile per uno non
proprio bravissimo come me. In questa versione secant è una funzione
della classe a, a me ciò non serve, secant può essere una funzione
generica, ma deve essere richiamata da una funzione della classe a
(chiamiamola calcola, ad esempio), quando calcola richiama secant
dovrà passargli un puntatore a se stessa (this?) ed un puntatore alla
funzione da richiamare (A::*f?). E' possibile farlo? Come? Posto anche
il codice della funzione secant, magari a qualcuno può essere utile.
double secant(double (*f)(double),double x0, double x1, double eps, int
maxit)
{
    if( x0 > x1 ) swap(x0,x1);
    double x;
    int n = 0;
    do {
        double y0,y1;
		y0 = (*f)(x0);
		y1 = (*f)(x1);
		if (ABS(y1 - y0) < 0.001) y1 += 0.001;
        x = (x0 * y1 - x1 * y0) / (y1 - y0), x0 = x1, x1 = x;
        n++;
    } while (n < maxit && ABS(x1 - x0) >= eps);
 
	return x;
}

 E' possibile farlo? Come?
Non devi modificare poi molto:
#include <iostream>
template <class T>
double secant(T& t, double (T::*f)(double))
{
     return (t.*f)(2.3);
}
class A
{
     double f1(double val) { return val*2; }
     double f2(double val) { return val/2; }
public:
	double calc()
	{
		return secant(*this, &A::f1);
	}
};
int main()
{
     A a;
     std::cout << a.calc() << std::endl;
}
Kiuhnm

Perfetto, grazie. Se passi da Napoli hai una pizza pagata.
Mi dava ancora un errore ma scrivendo la funzione h nel header file ho
risolto, non è bellissimo ma a mali estremi ...