问题
I have a class and one of its member functions is actually a function pointer. That way the user can overwrite what does this function do. I unfortunately have some difficulties running this function. I use g++ to compile.
Below is the code:
#include <iostream>
using namespace std;
double fcn_mod(const double &phit){
return 1.2+phit;
}
class Object{
public:
Object() {
fcn_ptr = (double (*)(const double &)) &Object::fcn_default;
}
double (*fcn_ptr)(const double &) = NULL;
private:
double fcn_default(const double &phit){
return 3.2+phit;
}
};
int main(){
Object test1,test2;
cout << (test1.*fcn_ptr)(2) << endl; // can not compile here
test2.fcn_ptr = &fcn_mod;
cout << (test2.*fcn_ptr)(2) << endl; // and here
cout << "test" << endl;
}
The error message is:
erreur: ‘fcn_ptr’ was not declared in this scope
+++++ UPDATE 1 +++++
Taking into account the comments, here is a cleaner version:
#include <iostream>
using namespace std;
double fcn_mod(const double &phit){
return 1.2+phit;
}
double fcn_default(const double &phit){
return 3.2+phit;
}
class Object{
public:
double (*fcn_ptr)(const double &) = NULL;
Object() {
fcn_ptr = &fcn_default;
}
};
int main(){
Object test1,test2;
cout << (test1.*fcn_ptr)(2) << endl; // can not compile here
test2.fcn_ptr = &fcn_mod;
//cout << (test2.*fcn_ptr)(2) << endl; // and here
cout << "test" << endl;
}
This one is also a better approach:
#include <iostream>
using namespace std;
double fcn_mod(const double &phit){
return 1.2+phit;
}
class Object{
public:
Object() {
fcn_ptr = &fcn_default;
}
double (*fcn_ptr)(const double &) = NULL;
private :
static double fcn_default(const double &phit){
return 3.2+phit;
}
};
int main(){
Object test1,test2;
cout << (test1.*fcn_ptr)(2) << endl; // can not compile here
test2.fcn_ptr = &fcn_mod;
cout << (test2.*fcn_ptr)(2) << endl; // and here
cout << "test" << endl;
}
+++++ UPDATE 2 +++++
What if I want to access members of the class through this function?
The simplest solution will not be able to give access to the class member (aa) from within fcn_mod.
#include <iostream>
using namespace std;
double fcn_mod(const double &phit){
return 1.2 + phit + aa*0.001; // can not compile here
}
class Object{
public:
Object() {
fcn_ptr = &Object::fcn_default;
aa = 4;
}
double (*fcn_ptr)(const double &) = NULL;
double aa;
private:
static double fcn_default(const double &phit){
return 3.2 + phit + aa*0.001; // and here
}
};
int main(){
Object test1,test2;
cout << (test1.fcn_ptr)(2) << endl;
test2.fcn_ptr = &fcn_mod;
cout << (test2.fcn_ptr)(2) << endl;
cout << "test" << endl;
}
But the solution using std::bind and std::function does not either. Can I pass a kind of "static" parameter to the function pointer?
I added a gateway function.
#include <iostream>
using namespace std;
double fcn_mod(const double &phit){
return 1.2 + phit;
}
class Object{
public:
Object() {
fcn_ptr = &Object::fcn_default;
aa = 4;
}
double do_something(const double &phit){
return this->fcn_ptr(phit+aa*0.001);
}
double (*fcn_ptr)(const double &);
double aa;
private:
static double fcn_default(const double &phit){
return 3.2 + phit;
}
};
int main(){
Object test1,test2;
cout << test1.do_something(2) << endl; // can not compile here
test2.fcn_ptr = &fcn_mod;
cout << test2.do_something(2) << endl; // and here
cout << "test" << endl;
}
回答1:
You do not have a class with a "function which is a function pointer", but rather a class with a data member which is a function pointer. This is an important distinction as the function won't receive a this pointer, nor will it have access to protected or private members.
You've declared your function pointer correctly, but you need to use the .fcn_ptr
rather than .*fcn_ptr
. I believe this is sufficient to solve your problem.
Do note that you're using old C style function pointer syntax. You may want to learn the C++ function pointer alternatives including std::function
.
回答2:
What you're trying to do isn't going to work. A pointer to a non-static member function is not the same as a pointer to a free function, because unlike the latter, the former must be invoked on an instance of the object. So you cannot declare a variable of one type and assign a pointer to a function of the other type to it.
First, let's fix half your code:
Since fcn_ptr
is a pointer to member function, it's definition needs to be:
double (Object::*fcn_ptr)(const double &) = NULL;
Then, the cast in your constructor is invalid. You're attempting to cast a pointer to a member function to a pointer to a free function. Get rid of the cast.
Object() : fcn_ptr(&Object::fcn_default)
{}
Finally, when you invoke fcn_ptr
, you can't simply conjure it out of thin air. It is a data member of Object
and so you need an instance of the class to access fcn_ptr
. So call it as:
(test1.*(test1.fcn_ptr))(2)
Make all these changes, and half your code will compile and produce the correct result. Live demo
The other half, where you try to assign a pointer to a free function to fcn_ptr
still won't work because of the reasons stated earlier. The way to fix this is to use std::function
instead of a function pointer.
class Object{
public:
Object() : fcn_ptr(std::bind(&Object::fcn_default, this, std::placeholders::_1))
{}
std::function<double(double const&)> fcn_ptr;
private:
double fcn_default(const double &phit){
return 3.2+phit;
}
};
And then use it as:
cout << (test1.fcn_ptr)(2) << endl;
test2.fcn_ptr = &fcn_mod;
cout << (test2.fcn_ptr)(2) << endl;
Live demo
来源:https://stackoverflow.com/questions/24195579/class-member-function-as-function-pointer