Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    [C++] Puntatori a funzione

    Ciao a tutti.
    Sto cercando di capire come utilizzare dei puntatori a funzione, che mi servirebbero per rendere flessibili alcuni programmi di fisica computazionale che sto scrivendo. Ho letto un po' in internet e questo é il programma che ho creato (integrazione numerica con lo schema di Euler di una palla da baseball con e senza attrito dell'aria):
    codice:
    #include <iostream>
    using std::cout;
    using std::endl;
    
    #include <array>
    using std::array;
    
    #include <utility>
    using std::move;
    
    #include <initializer_list>
    using std::initializer_list;
    
    #include <cmath>
    using std::sqrt;
    using std::sin;
    using std::cos;
    
    void euler(
    	double dt,
    	array<double,2>& r_old,
    	array<double,2>& v_old,
    	array<double,2> (*f)(array<double,2>, array<double,2>))
    {
    	array<double,2> r_new{{r_old[0] + dt * v_old[0], r_old[0] + dt * v_old[0]}};
    	array<double,2> v_new{{v_old[0] + dt * f(r_old,v_old)[0], v_old[0] + dt * f(r_old,v_old)[0]}};
    	
    	r_old = r_new;
    	v_old = v_new;
    }
    
    array<double,2> accel(array<double,2> x, array<double,2> v)
    {
    	array<double,2> a{{0,-9.81}};
    	
    	return std::move(a);
    }
    
    array<double,2> accel_air(array<double,2> x, array<double,2> v)
    {
    	double air_cst(-0.5*0.35*1.2*4.3e-3/0.145);
    	double norm(sqrt(v[0]*v[0] + v[1]*v[1]));
    
    	array<double,2> a{{air_cst * norm * v[0], air_cst * norm * v[1] - 9.81}};
    }
    
    int main()
    {
    	double speed(50.);
    	double angle(45.);
    	double tau(0.1);
    	double h_init(1.);
    
    	array<double,2> r{{0.,h_init}};
    	array<double,2> v{{speed*cos(angle*M_PI/180), speed*sin(angle*M_PI/180)}};
    	
    	do
    	{
    		cout << r[0] << ' ' << r[1] << endl;
    		
    		euler(tau, r, v, accel(r,v));
    	}
    	while(r[1] > 0);
    	
    	cout << endl;
    	
    	do
    	{
    		cout << r[0] << ' ' << r[1] << endl;
    		
    		euler(tau, r, v, accel_air(r,v));
    	}
    	while(r[1] > 0);
    
    	return 0;
    }
    Comilando con g++-4.7 ottengo però gli errori seguenti, che proprio non riesco a capire:
    codice:
    g++-mp-4.7 -std=c++11 Baseball.cpp -o Baseball
    Baseball.cpp: In function 'int main()':
    Baseball.cpp:61:30: error: cannot convert 'std::array<double, 2ul>' to 'std::array<double, 2ul> (*)(std::array<double, 2ul>, std::array<double, 2ul>)' for argument '4' to 'void euler(double, std::array<double, 2ul>&, std::array<double, 2ul>&, std::array<double, 2ul> (*)(std::array<double, 2ul>, std::array<double, 2ul>))'
    Baseball.cpp:71:34: error: cannot convert 'std::array<double, 2ul>' to 'std::array<double, 2ul> (*)(std::array<double, 2ul>, std::array<double, 2ul>)' for argument '4' to 'void euler(double, std::array<double, 2ul>&, std::array<double, 2ul>&, std::array<double, 2ul> (*)(std::array<double, 2ul>, std::array<double, 2ul>))'
    Grazie.
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  2. #2
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    131
    quello che intende dire è:

    Originariamente inviato da g++
    La funzione euler ha come quarto parametro un puntatore a funzione, mentre quello che ritorna da accel o accel_air è un array<double,2>. E' impossibile eseguire un cast e quindi non ho intenzione di continuare a compilare.



    Quando scrivi
    codice:
    euler(tau, r, v, accel(r,v));
    accel viene eseguita e il suo valore di ritorno viene passato a euler.. nessun puntantore a funzione viene passato.
    Dovresti scrivere
    codice:
    euler(tau, r, v, accel);

  3. #3
    Originariamente inviato da XAlbeX
    quello che intende dire è:


    :D


    Quando scrivi
    codice:
    euler(tau, r, v, accel(r,v));
    accel viene eseguita e il suo valore di ritorno viene passato a euler.. nessun puntantore a funzione viene passato.
    Dovresti scrivere
    codice:
    euler(tau, r, v, accel);
    Grazie mille. Che stupido che sono. Quindi il nome di una funzione lo posso considerare come un puntatore alla porzione di codice da eseguire (o qualcosa del genere)?

    Ora compila, ma gli oggetti partono per la tangente, cioè volano in linea retta e non capisco perché... Qualche idea?

    codice:
    #include <iostream>
    using std::cout;
    using std::endl;
    
    #include <array>
    using std::array;
    
    #include <utility>
    using std::move;
    
    #include <initializer_list>
    using std::initializer_list;
    
    #include <cmath>
    using std::sqrt;
    using std::sin;
    using std::cos;
    
    void euler(
    	double dt,
    	array<double,2>& r_old,
    	array<double,2>& v_old,
    	array<double,2> (*f)(array<double,2>, array<double,2>))
    {
    	array<double,2> r_new{{r_old[0] + dt * v_old[0], r_old[0] + dt * v_old[0]}};
    	array<double,2> v_new{{v_old[0] + dt * f(r_old,v_old)[0], v_old[0] + dt * f(r_old,v_old)[0]}};
    	
    	r_old = r_new;
    	v_old = v_new;
    }
    
    array<double,2> accel(array<double,2> x, array<double,2> v)
    {
    	array<double,2> a{{0,-9.81}};
    	
    	return std::move(a);
    }
    
    array<double,2> accel_air(array<double,2> x, array<double,2> v)
    {
    	double air_cst(-0.5*0.35*1.2*4.3e-3/0.145);
    	double norm(sqrt(v[0]*v[0] + v[1]*v[1]));
    
    	array<double,2> a{{air_cst * norm * v[0], air_cst * norm * v[1] - 9.81}};
    	
    	return std::move(a);
    }
    
    int main()
    {
    	double speed(50.);
    	double angle(45.);
    	double tau(0.1);
    	double h_init(1.);
    
    	array<double,2> r{{0.,h_init}};
    	array<double,2> v{{speed*cos(angle*M_PI/180), speed*sin(angle*M_PI/180)}};
    	
    	do
    	{
    		cout << r[0] << ' ' << r[1] << endl;
    		
    		euler(tau, r, v, accel);
    	}
    	while(r[1] > 0);
    	
    	cout << endl;
    	
    	array<double,2> r_air{{0.,h_init}};
    	array<double,2> v_air{{speed*cos(angle*M_PI/180), speed*sin(angle*M_PI/180)}};
    	
    	do
    	{
    		cout << r[0] << ' ' << r[1] << endl;
    		
    		euler(tau, r_air, v_air, accel_air);
    	}
    	while(r_air[1] > 0);
    
    	return 0;
    }
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  4. #4
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    131
    codice:
    array<double,2> r_new{{r_old[0] + dt * v_old[0], r_old[0] + dt * v_old[0]}}; 
    array<double,2> v_new{{v_old[0] + dt * f(r_old,v_old)[0], v_old[0] + dt * f(r_old,v_old)[0]}};
    dovrebbe essere
    codice:
    array<double,2> r_new{{r_old[0] + dt * v_old[0], r_old[1] + dt * v_old[1]}}; 
    array<double,2> v_new{{v_old[0] + dt * f(r_old,v_old)[0], v_old[1] + dt * f(r_old,v_old)[1]}};
    perché calcoli due volte f(r_old,v_old)?
    controlla se ora funziona

  5. #5
    Originariamente inviato da XAlbeX
    codice:
    array<double,2> r_new{{r_old[0] + dt * v_old[0], r_old[0] + dt * v_old[0]}}; 
    array<double,2> v_new{{v_old[0] + dt * f(r_old,v_old)[0], v_old[0] + dt * f(r_old,v_old)[0]}};
    dovrebbe essere
    codice:
    array<double,2> r_new{{r_old[0] + dt * v_old[0], r_old[1] + dt * v_old[1]}}; 
    array<double,2> v_new{{v_old[0] + dt * f(r_old,v_old)[0], v_old[1] + dt * f(r_old,v_old)[1]}};
    perché calcoli due volte f(r_old,v_old)?
    controlla se ora funziona


    Che stupido! Grazie mille!
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.