CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Nov 2010
    Posts
    4

    Member function as function argument

    I'm having problems with using a simple static function I have defined & declared to calculate the definite integral of a function that is passed to it as an argument. Sorry in advanced for posting so much code. Your help is very much appreciated.

    Math.h _____________________________________________________
    class Math
    {
    public:
    static double integrate(double (*f)(double x), double a, double b);
    };

    Math.cpp _____________________________________________________
    #include "Math.h"

    double Math::integrate(double (*f)(double x), double a, double b)
    {
    int m = 1000;
    double dt = (b-a)/m;
    double c = 0;

    for(int i = 0; i<m; i++)
    {
    c += (*f)(a+i*dt);
    }

    return c/m;
    }

    Model.h _______________________________________________________
    #include <cmath>
    #include "Math.h"

    #define pi 3.141592

    class Model
    {
    private:
    double y, z;
    double C;
    double L;
    double R_L;
    double V_in;
    double V_out;
    double V_f;
    double RDSON;
    Math math;

    double tau_charging();

    double T_charging();

    double omega();

    double T_discharging();

    double F_switching();

    double L_max();

    double i_L_charging(double t);

    double I_d_avg();

    double R_D();

    double i_L_discharging(double t);

    double E_L_charging(double t);

    double E_L_discharging(double t);

    double E_R_L_charging(double t);

    double E_R_L_discharging(double t);

    double E_RDSon_charging(double t);

    double E_D_discharging(double t);

    double Eff_charging(double t);

    double Eff_discharging(double t);

    double Eff_avg_charging();

    double Eff_avg_discharging();

    public:

    double Eff_avg();

    double P_out();

    double MaxLoad();

    void set_y(double a);
    void set_z(double a);
    void set_C(double a);
    void set_L(double a);
    void set_R_L(double a);
    void set_V_in(double a);
    void set_V_out(double a);

    double get_y();
    double get_z();
    double get_C();
    double get_L();
    double get_R_L();
    double get_V_in();
    double get_V_out();
    };

    Model.cpp _____________________________________________
    #include "Model.h"

    double Model::tau_charging()
    {
    return L/(R_L+RDSON);
    }

    double Model::T_charging()
    {
    return y*tau_charging();
    }

    double Model:mega()
    {
    return 1.0/sqrt(L*C);
    }

    double Model::T_discharging()
    {
    return (2*pi)/(4*omega());
    }

    double Model::F_switching()
    {
    return 1/(T_charging() + T_discharging());
    }

    double Model::L_max()
    {
    return 0;
    }

    double Model::i_L_charging(double t)
    {
    return V_in/(R_L+RDSON) - V_in/(R_L+RDSON)*exp(-t/tau_charging());
    }

    double Model::I_d_avg()
    {
    return math.integrate(&Model::i_L_charging, 0.0, T_charging());
    }

    double Model::R_D()
    {
    return V_f/I_d_avg();
    }

    double Model::i_L_discharging(double t)
    {
    return exp((t*(R_D()+R_L))/(2*z*L_max()))*cos(omega()*t)*i_L_charging(T_charging());
    }

    double Model::E_L_charging(double t)
    {
    return 0.5*z*L_max()*pow(i_L_charging(t),2);
    }

    double Model::E_L_discharging(double t)
    {
    return 0.5*z*L_max()*pow(i_L_discharging(t),2);
    }

    double Model::E_R_L_charging(double t)
    {
    return 0;
    }

    double Model::E_R_L_discharging(double t)
    {
    return 0;
    }

    double Model::E_RDSon_charging(double t)
    {
    return 0;
    }

    double Model::E_D_discharging(double t)
    {
    return 0;
    }

    double Model::Eff_charging(double t)
    {
    return E_L_charging(t)/(E_L_charging(t)+E_R_L_charging(t)+E_RDSon_charging(t));
    }

    double Model::Eff_discharging(double t)
    {
    return E_L_discharging(t)/(E_L_discharging(t)+E_R_L_discharging(t)+E_D_discharging(t));
    }

    double Model::Eff_avg_charging()
    {
    return 0;
    }

    double Model::Eff_avg_discharging()
    {
    return 0;
    }

    double Model::Eff_avg()
    {
    return (Eff_avg_charging()+Eff_avg_discharging())/2;
    }

    double Model::P_out()
    {
    return (E_L_discharging(0.0)-E_R_L_discharging(T_discharging())-E_D_discharging(T_discharging()))/(T_charging()+T_discharging());
    }

    double Model::MaxLoad()
    {
    return pow(V_in,2)/P_out();
    }

    /*
    Get and set functions
    */
    void Model::set_y(double a)
    {
    y=a;
    }
    void Model::set_z(double a)
    {
    z=a;
    }
    void Model::set_C(double a)
    {
    C=a;
    }
    void Model::set_L(double a)
    {
    L=a;
    }
    void Model::set_R_L(double a)
    {
    R_L=a;
    }
    void Model::set_V_in(double a)
    {
    V_in=a;
    }
    void Model::set_V_out(double a)
    {
    V_out=a;
    }

    double Model::get_y()
    {
    return y;
    }
    double Model::get_z()
    {
    return z;
    }
    double Model::get_C()
    {
    return C;
    }
    double Model::get_L()
    {
    return L;
    }
    double Model::get_R_L()
    {
    return R_L;
    }
    double Model::get_V_in()
    {
    return V_in;
    }
    double Model::get_V_out()
    {
    return V_out;
    }

    The error from GCC compiler is:
    D:\My Projects\In progress\Solar panel system\My inverter\Calculations\Mathematica\C++\DC-DC Converter\Model.cpp||In member function `double Model::I_d_avg()':|
    D:\My Projects\In progress\Solar panel system\My inverter\Calculations\Mathematica\C++\DC-DC Converter\Model.cpp|40|error: no matching function for call to `Math::integrate(double (Model::*)(double), double, double)'|
    D:\My Projects\In progress\Solar panel system\My inverter\Calculations\Mathematica\C++\DC-DC Converter\Math.h|5|note: candidates are: static double Math::integrate(double (*)(double), double, double)|
    ||=== Build finished: 1 errors, 0 warnings ===|


    Please note that this DOES work:
    main.cpp ________________________________________________________
    #include <iostream> // For UI I/O
    #include <cmath>
    #include <fstream>
    #include "Model.h"

    using namespace std;

    double f(double a);

    int main()
    {
    Model m;

    cout << "Integrating..." << endl;

    cout << "The answer is: " << Math::integrate(f,0.0,1.0);

    cout << endl;
    system("pause");
    return 0;
    }

    double f(double a)
    {
    return a;
    }

  2. #2
    Join Date
    Jan 2001
    Posts
    253

    Re: Member function as function argument

    Your problem is that you can't pass a pointer to a member function to a routine that expects a pointer to a normal function.

    You need to provide an adaptor that will make bind the model object with the member function.

    I would approach this by first modifying the Math class so that the function passed in the the Math integrate function is templated. This is to allow it to be called with a function object (and not just a static / global function).

    Code:
    class Math
    {
    public:
       template <class FN>
       static double integrate(FN f, double a, double b)
       {
          int m = 1000;
          double dt = (b-a)/m;
          double c = 0;
    
          for(int i = 0; i<m; i++)
          {
             c += f(a+i*dt);
          }
    
          return c/m;
       }
    };
    Once this change is made, you can provide an adaptor that binds a Model object with a member function of the Model. One way that you could do this is as follows:

    Code:
    class Model
    {
       typedef double(Model::*ModelMemFn)(double t);
       class BoundModelFunc
       {
       public:
          BoundModelFunc(Model* model, ModelMemFn func) : model(model), func(func)
          {
          }
    
          double operator()(double t) const
          {
             return ((model)->*(func))(t);
          }
    
       private:
          Model* model;
          ModelMemFn func;
       };
    
       double ModelIntegrate(ModelMemFn memfunc, double a, double b)
       {
          return Math::integrate(BoundModelFunc(this, memfunc), a, b);
       }
    
    public:
       double T_charging();
       double i_L_charging(double t);
       double I_d_avg();
    };
    
    
    double Model::I_d_avg()
    {
       return ModelIntegrate(&Model::i_L_charging, 0.0, T_charging());
    
       // or
       // return Math::integrate(BoundModelFunc(this, &Model::i_L_charging, 0.0, T_charging();
    }
    I chose to provide a private helper function called ModelIntegrate, which makes the BoundModelFunc and calls the Math::integrate. This allows the call to look similar to your original call. If you prefer, you could directly call the Math::integrate (as I showed in the comment in Model::I_d_avg).

    Best regards,
    John

  3. #3
    Join Date
    Nov 2010
    Posts
    4

    Resolved Re: Member function as function argument

    Thanks for your help John. It works beautifully now. Although I wish the process of passing member functions as arguments would prove to be more intuitive. I suppose that's what you get from a programming language that has been patched up through the decades.

  4. #4
    Join Date
    Nov 2010
    Posts
    4

    Re: Member function as function argument

    I have another problem.

    This function is in Model.cpp:

    double Model::E_R_L_charging(double t)
    {
    return ModelIntegrate(&Model::i_L_charging, 0, t);
    }

    However for the first argument of ModelIntegrate I would like to pass this:
    (I show it in mathematical form)
    i_L_charging^2*R_L

    How do I translate what I want into C++ code?
    So something like this:

    double Model::E_R_L_charging(double t)
    {
    return ModelIntegrate(i_L_charging^2*R_L, 0, t);
    }

    Thanks for your help.

  5. #5
    Join Date
    Jan 2001
    Posts
    253

    Re: Member function as function argument

    The easiest way is to just make a new member function of the Model:

    Code:
    // needed include file:
    #include <cmath>   // or <math.h>
    Code:
    // using direct math
    double ChargingFormula(double t)
    {
       double charge = i_L_charging(t);
       return charge * charge * R_L;
    }
    Code:
    // using pow()
    double ChargingFormula(double t)
    {
       return pow(i_L_charging(t), 2) * R_L;
    }
    You can then use the same ModelIntegrate, passing the address of this function.

    Code:
    double Model::E_R_L_charging(double t)
    {
       return ModelIntegrate(&Model::ChargingFormula, 0, t);
    }
    Note that ^ means XOR in the C++ language and there is no operator that raises to a power. Instead you either have to do the math directly or call the library routine pow. For a simple case like squaring, it is probably better to do the math directly. For a higher power (or a non-integer power), you can use pow.

    You should also use code tags around any code you post. You can do this by putting [CODE] before the code block and [/CODE] after the code block.

    Best regards,
    John

  6. #6
    Join Date
    Nov 2010
    Posts
    4

    Re: Member function as function argument

    Thanks for your help again John.

    Regards Johnny.

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Member function as function argument

    Quote Originally Posted by wasssup1990 View Post
    Although I wish the process of passing member functions as arguments would prove to be more intuitive.
    Pointers to non-static member functions and pointers to "free" or global functions are not the same thing, and never have been the same thing.
    I suppose that's what you get from a programming language that has been patched up through the decades.
    There was no "patching" done for member function pointers -- that's the way it's always been.

    http://www.parashift.com/c++-faq-lit...o-members.html

    C++ is not "patched" up. Any changes to the language must go through ANSI/ISO, and those changes or additions do not make it into the language for several years. C++ was officially standardized in 1998, with a revision in 2003. If you get a copy of the ANSI/ISO C++ specification, you will see it is hardly anything that is "patched up".

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; November 2nd, 2010 at 11:03 AM.

  8. #8
    Join Date
    Jan 2001
    Posts
    253

    Re: Member function as function argument

    Hi Johnny,

    When I provided the original solution, I was just going for a quick and dirty solution.

    There is a solution which doesn't require writing the BoundModelFunc adaptor (assuming that it is supported by your compiler).

    The following works with VS2010 and may work with your compiler (I don't have gcc, so I can't check):

    Code:
    // include file needed
    #include <functional>
    Code:
    class Model
    {
    private:
       typedef double(Model::*ModelMemFn)(double t);
    
       double ModelIntegrate(ModelMemFn memfunc, double a, double b)
       {
          std::function<double(double)> boundFunc = std::bind1st(std::mem_fun(memfunc), this);
          return Math::integrate(boundFunc, a, b);
       }
    };
    This creates an std::function object which binds the Model object with the particular member function without needing to write an adaptor class.

    You may be able to replace the ModelIntegrate from the previous post with this code and remove BoundModelFunc.

    Best regards,
    John

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured