Pass a non static Function Pointer of a Class as Parameter
I need a Function like 开发者_如何学JAVAthat:
class Class_A
{
...
bool ShowVariableConstituents( CString ( * ValueOutput )( double ) );
...
}
bool Class_A::ShowVariableConstituents( CString ( * ValueOutput )( double ) )
{
double dUncalculatedValue;
....
if( ValueOutput )
{
CString strValue = ValueOutput( dUncalculatedValue );
}
....
}
Here is an example how i need to use it:
class Class_B : Class_A
{
...
int Calculate();
CString ValueOutput( double dValue );
...
}
CString Class_B::ValueOutput( double dValue )
{
CString strValue;
strValue.Format("%6.2f", ( dValue / m_dAmount * 100 ) );
return strValue;
}
int Class_B::Calculate()
{
...
ShowVariableConstituents( & Class_B::ValueOutput );
...
}
I get the Error:
Error 1 error C2664: ' Class_A::ShowVariableConstituents': conversion of Parameter 1 from 'CString (__thiscall Class_B::* )(double)' in 'CString (__cdecl *)(double)' not possible
Can you help me do it right?
regards camelord
To make it possible to pass pointers to member functions you should modify your function as follows:
bool ShowVariableConstituents( CString ( Class_A::* ValueOutput )( double ) )
But it will not help since you want to pass the pointer to Class_B::ValueOutput
and Class_A
doesn't know anything about Class_B
.
Your option is to make your function template:
template<typename UnaryOperator>
bool Class_A::ShowVariableConstituents( UnaryOperator op )
{
double dUncalculatedValue;
CString strValue = op( dUncalculatedValue );
return true; // false ?
}
Then you could use it as follows:
int Class_B::Calculate()
{
ShowVariableConstituents( std::bind1st( std::mem_fun( &Class_B::ValueOutput ), this ) );
return 0; // put your code here
}
I believe the answer you're looking for is the answer to my question here:
std::tr1::function and std::tr1::bind
my adapt_integrate
is your A::ShowVariableConstituents
and my integrand
is your ValueOutput
. It's not completely the same, but the issue you are having is that a non-static class member function will implicitely pass a this
reference to the class object that it "resides" in. I believe that the __thiscall Class_B::*
part is exactly that. You will need to wrap the function you want to call in a static member function.
If needed, I could try translating the answer to my question to code in your case, but I don't think I'm capable enough :)
You can not send a pointer-to-method to a function/method receiving a pointer-to-a-free-function.
Think about it, a method requires a pointer to the object (this
) on which it is applied.
Edit:
In your case, if all clients of A::ShowVariableConstituents actually derive from A (such as B does) than you might have a virtual method CString A::ValueOutput(double)
which would be overrided in the derived classes and called from A::ShowVariableConstituents().
BTW, this would be an instance of the Template method design pattern.
Please read up on why pointers to non-static members are not supported. http://www.parashift.com/c++-faq-lite/pointers-to-members.html
If you are looking to build something similar to a closure where you can pass an object's member function around and modify state on that object anonymously through this function, you could either pass "this" into each function (which isn't always possible), or you can use functors.
A functor is a class that is comprised mainly of just an operator(). What you'd do (and I haven't tested this, EVER) is create a base class with pure virtual operator(). In your derived classes, you can create a pointer inside the derived class to point to the object whose state you wish to modify. You would also implement a virtual operator() in the derived classes.
Inside the class whose state you want to modify, you create an instance of this derived class (which must be a friend). You instantiate this derived object with the "this" pointer of the class you wish to modify.
So when you want to pass this functor around in your code, you would pass state_modified_class.derived_functor_class instead of a pointer to a member function of state_modified_class. Your function showvariableconstituents would take a parameter of base_functor_class instead of a function pointer.
As I said, this is all theory. I don't know if it will actually work. I'm not a C++ expert.
edit:
#include <QtCore/QCoreApplication>
#include <iostream>;
using namespace std;
class BaseFunctor
{
public:
virtual void operator()() = 0;
};
class StateMod
{
friend class DerivedFunctor;
public:
class DerivedFunctor : public BaseFunctor
{
public:
DerivedFunctor(StateMod * tempths)
{
ths = tempths;
}
virtual void operator()()
{
ths->temp++;
}
private:
StateMod * ths;
};
DerivedFunctor derived;
StateMod(int x = 0) : derived(this)
{
this->temp = x;
}
void printTemp()
{
cout << "temp: " << temp << endl;
}
private:
int temp;
};
class demonstration
{
public:
void doit(BaseFunctor & basefunct)
{
basefunct();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
StateMod moddy;
demonstration demo;
moddy.printTemp();
demo.doit(moddy.derived);
moddy.printTemp();
return a.exec();
}
精彩评论