-
November 1st, 2010, 04:45 AM
#1
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;
}
-
November 1st, 2010, 10:12 AM
#2
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
-
November 1st, 2010, 10:32 PM
#3
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.
-
November 1st, 2010, 10:50 PM
#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.
-
November 2nd, 2010, 07:58 AM
#5
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
-
November 2nd, 2010, 10:29 AM
#6
Re: Member function as function argument
Thanks for your help again John.
Regards Johnny.
-
November 2nd, 2010, 10:58 AM
#7
Re: Member function as function argument
Originally Posted by wasssup1990
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.
-
November 2nd, 2010, 02:35 PM
#8
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|