You don't need pointers to functions for this at all. You need either polymorphism or template specialisation.
Okay - I'll take pity and explain why your example2 code doesn't work, and then go through better approaches.
The reason the first example doesn't work is that what it needs is a pointer to member function, which is something distinct from a pointer to a function.
This is a version that will do what you intend
Code:
class example2{
private:
double afterswitch(){
cout<<"do something-02"<<endl;
return 0.0;
}
double beforeswitch(){
cout<<"do something else-02"<<endl;
return 0.0;
}
double (example2::*pf)(); // pf is a pointer to a member function not a pointer to a function
public:
example2():pf(&example2::beforeswitch){} // pf is initialised as the address of a member function
double workfunc(){
return (this->*pf)(); // call syntax for pointer to member
}
void controlfunc(){
pf=&example2::afterswitch; // note how pf is reassigned
}
};
The thing you're not understanding is that a non-static member function needs to be called in context of an object: some_object.member_function(). Since a member function is a different beast from a non-member function, a pointer to a member function and a pointer to a function are distinct types.
The mechanism for initialising such pointers is different (you need to use the full name example2::beforeswitch, rather than the unqualified name beforeswitch) and the ampersand is also necessary (whereas it is implied when converting a normal function name into a pointer to function).
Lastly, the calling syntax is different. If pf has been initialised to &example2::beforeswitch, then calling it via "(some_pointer_to_object->*pf)()" has the same effect as "some_pointer_to_object->beforeswitch()". The reason for the brackets around (this->*pf) is related to rules of operator precedence.
However, all that said, pointers to member functions have their uses (which I won't go into) but polymorphism and template specialisation are both better (less error prone) alternatives.
Polymorphism could be utilised thus;
Code:
class Base
{
public:
Base() {};
virtual double do_something() = 0;
virtual ~Base();
};
class Before: public Base
{
public:
Before() : Base() {};
double do_something();
};
double Before::do_something()
{
std::cout << "Before\n";
return 0.0
}
class After: public Base
{
public:
After() : Base() {};
double do_something();
};
double After::do_something()
{
std::cout << "After\n";
return 0.0
}
int main()
{
Base *x = new Before();
x->do_something();
Base *y = new After();
y->do_something();
delete x; // clean up. Note that Base's destructor must be virtual for this to work.
delete y;
}
Note that there is no "if()" statement in sight.
The advantage of the inheritance approach is that you can have any number of different classes derived from Base. And the compiler takes care of working out which function to call. In fact, the only decision you have to make is which type of object to create - the act of creating an object automatically associates that object with the correct function to call (Before::do_something() or After::do_something() respectively).
Base, in the above, is described as a "polymorphic base class".
The efficiency gain in this, if any, is not related to using a pointer. It is related to the fact that, for both objects x and y, the decision about what function to call is typically determined when the object is created, not when your code attempts to call the function.
If you want to have the decision made at compile time, then use template specialisation. For example;
Code:
template<int n> struct Example;
template<> struct Example<1>
{
double do_something() {std::cout << "Example 1\n"; return 0.0;};
};
template<> struct Example<2>
{
double do_something() {std::cout << "Example 2\n"; return 0.0;};
};
int main()
{
Example<1> x;
x.do_something(); // will call the first version of do_something() above
Example<2> y;
y.do_something(); // will call the second version of do_something() above
Example<3> z; // will result in compilation error since Example<3> has not been defined.
z.do_something(); //
return 0;
}
In this case, the decision about which function is determined when creating the object. The decision about what object to create is fixed at compile time.