Connecting Tech Pros Worldwide Help | Site Map

References to class functions

 
LinkBack Thread Tools Search this Thread
  #1  
Old July 22nd, 2005, 05:11 AM
Augasm
Guest
 
Posts: n/a
Default References to class functions

I'm trying to clean up a bunch of my code by building C++ classes for
commonly used code elements, and have run into a problem.

Allow me to preface this with a disclaimer that I am not formally
trained in C or C++, so if my english-syntax on the matter is
incorrect, I apologize, and, allowing for the high probability that my
english-syntax *will* be off, I will include my actual code, so as to
reduce confusion if possible.

My problem is in my numerical roots-finding class. The following bit
of code works just fine when
incorporated in ordinary linear code:

/* Include Numerical Recipes in C subroutines, specifically zbrak()
and rtsafe(), which are
* prototyped as follows:
* void zbrak(float (*fx)(float), float x1, float x2, int n, float
xb1[], float xb2[], int *nb);
* float rtsafe(void (*funcd)(float, float *, float *), float x1,
float x2, float xacc);
*/
#include "nr.c"

int static const subdivide = 20;
float const accuracy = 1E-15;
int const degree = 4;
int i;
float x1, x2, *x1a, *x2a, root;
float Kd1, Kd2,Mo;

float massbalance(float);
void dmassbalance(float, float *, float *);

int main (int argc, char *argv[]) {
...
Mo = 1E-9; // constraining value
Kd1 = 1E-10; // other parameters
Kd2 = 1E-8;

x1a = vector(1,degree);
x2a = vector(1,degree);

// Find roots of quadric equation
zbrak( massbalance, 0, Mo, subdivide, x1a, x2a, &degree);
for (i=1; i<=degree; i++) {
root = rtsafe( dmassbalance, x1a[i], x2a[i], accuracy );
monomer = root;
}
...
}

float massbalance(float M) {
return M + 2*pow(M,2)/Kd1 + 4*pow(M,4) /( pow(Kd1,2)*Kd2 ) -
Mo;
}

void dmassbalance(float M, float *v, float *dv) {
*v = M + 2*pow(M,2)/Kd1 + 4*pow(M,4)/( pow(Kd1,2)*Kd2 ) - Mo;
*dv = 1 + 4*M/Kd1 + 16*pow(M,3)/( pow(Kd1,2)*Kd2 );
}

The numerical recipes subroutines take the function name sans
parentheses as an argument, which I understand to mean that a pointer
to the function is passed to the nr.c subroutines, which of course in
turn call upon these functions to work their magic. The subroutines
pointed to (massbalance and dmassbalance) also require values Kd1,
Kd2, and Mo, which are not explicitly passed as arguments, but are
known to these functions given the scope of their declaration (I
guess).

Now this root-calculating code is something I want to capsulize in a
class, as I use it frequently, and most of the variables involved are
needed only for this code block--root is the only thing that I really
want to know in the end. So I try to go about things in the obvious
way by

#include "nr.c"

class quadric {
public:
float root;

int factor( float, float, float);

private:
int static const subdivide = 20;
float static const accuracy = 1E-15;
int static const degree = 4;
int i;
float x1, x2, *x1a, *x2a;
float Mo,Kd1,Kd2;

float massbalance(float);
void dmassbalance(float, float *, float *);
};

int quadric::factor( float Mo, float Kd1, float Kd2) {
x1a = vector(1,degree);
x2a = vector(1,degree);

// Find roots of quadric equation
zbrak( massbalance, 0, Mo, subdivide, x1a, x2a, &degree);
for (i=1; i<=degree; i++) {
root = rtsafe( dmassbalance, x1a[i], x2a[i], accuracy );
}
}

float quadric::massbalance(float M) {
return M + 2*pow(M,2)/Kd1 + 4*pow(M,4) /( pow(Kd1,2)*Kd2 ) -
Mo;
}

void quadric::dmassbalance(float M, float *v, float *dv) {
*v = M + 2*pow(M,2)/Kd1 + 4*pow(M,4)/( pow(Kd1,2)*Kd2 ) - Mo;
*dv = 1 + 4*M/Kd1 + 16*pow(M,3)/( pow(Kd1,2)*Kd2 );
}

Which is then instituted by something like

#include "quadric.c"

quadric oligomericMo;
float M0;

int main(int argc, char *argv[]) {
M0 = 1E-9;
oligomericMo.factor(M0,1E-8,1E-10);
cout << oligomericMo.root << endl;
}

It makes the most sense from a code-organization point of view to have
massbalance() and dmassbalance be private class-member functions to
'quadric', as their detail is unimportant to the use of them, and
indeed if I declare and specify these functions in a broader scope,
the variables Mo, Kd1, and Kd2 are not available to these functions
anyway.

However, as listed above, when trying to compile I get
quadric.c: In member function `int quadric::factor(float, float,
float)':
quadric.c:33: error: argument of type `float (quadric::)(float)' does
not match `float (*)(float)'
quadric.c:35: error: argument of type `void (quadric::)(float, float*,
float*)'
does not match `void (*)(float, float*, float*)'

where lines 33 and 35 refer to zbrak and rtsafe function calls with
massbalance and dmassbalance (attempted) pointer arguments
respectively. I understand this to mean that as class-member
functions, massbalance and dmassbalance sans parenthesis are *not*
handled as a pointer to a function. I have found some rhetoric out
there which I think debates whether it is possible to use a pointer to
a class-member function and how, but I am not expert enough to pick
through it and work out what the conclusion is. I have tried some
workarounds which were too naive and amateur to waste your time with
(particularly as they achieved less success than the current degree of
disfunctionality).

So, finally the formal question: How can I prototype/define my
functions massbalance and dmassbalance so that they fit the 'float
(*fx)(float)' and 'void (*funcd)(float, float *, float *)' types
expected by zbrak and rtsafe respectively?

Immense thanks and praise to anybody who can show me the light!

  #2  
Old July 22nd, 2005, 05:11 AM
Gianni Mariani
Guest
 
Posts: n/a
Default Re: References to class functions

Augasm wrote:[color=blue]
> I'm trying to clean up a bunch of my code by building C++ classes for
> commonly used code elements, and have run into a problem.
>[/color]
....[color=blue]
>
> It makes the most sense from a code-organization point of view to have
> massbalance() and dmassbalance be private class-member functions to
> 'quadric', as their detail is unimportant to the use of them, and
> indeed if I declare and specify these functions in a broader scope,
> the variables Mo, Kd1, and Kd2 are not available to these functions
> anyway.
>
> However, as listed above, when trying to compile I get
> quadric.c: In member function `int quadric::factor(float, float,
> float)':
> quadric.c:33: error: argument of type `float (quadric::)(float)' does
> not match `float (*)(float)'
> quadric.c:35: error: argument of type `void (quadric::)(float, float*,
> float*)'
> does not match `void (*)(float, float*, float*)'
>
> where lines 33 and 35 refer to zbrak and rtsafe function calls with
> massbalance and dmassbalance[/color]


You can use the pointer to member syntax:

class Xoo;

void FunctionProto( bool (Xoo::*Parameter)( float ), Xoo * param );


class Xoo
{
public:
bool Func1( float );
bool Func2( float );
};

int main()
{

Xoo xoo[1];

FunctionProto( &Xoo::Func1, xoo );

}

void FunctionProto( bool (Xoo::*Parameter)( float ), Xoo * param )
{
(param->*Parameter)( 2.3f );
}

[color=blue]
>
> Immense thanks and praise to anybody who can show me the light![/color]

Any praise accepted graciously .... :-)

 

Bookmarks

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Popular Articles

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over 220,840 network members.