Link to home
Start Free TrialLog in
Avatar of Xertunus
Xertunus

asked on

Saving a function in a variable

Is it possible to save a function (not a value) in a variable, to evaluate it later???
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nietod
nietod

If you have functions that have the same signature--same calling convention, same parameters and same return values like

int Add(int x,int y)
{
   return x+y;
};

and

int Sub(int x,int y)
{
   return x - y;
};

Then you can create a pointer that can point to any of these functions.  At typedef for this pointer makes things easier, in this case it would be

typedef int (*FunPrtTyp)(int x,int y);

continues
You can declare then pointer a pointer of this type, iniitialze it to one of the functions and call the function with the pointer like

FunPtrTyp FunPtr;

if (OperationTyp == AddOperatio)
    FunPtr = &Add; // Set pointer to the add function.
   // FunPtr = Add; is also a legal syntax for this.
else
    FunPtr = ⋐ // Set pointer to the subtact function.

   *  *  *

 // Use the function pointer as follows.
   int Result = (*FunPtr)(5,3); // Does 5+3 or 5-3;
// also "FunPtr(5,3);" is a legal syntax.

continues
Obviously the function pointer can be passed to or returned from functions aand "saved till later" just like any pointer.

Now this same thing can be accomplished in a more C++ manor using classes.  This technique is so common that the classes used in this way are given a name--"functor".  A functor could be considered any class that has virtual functions, but usually it is a class with no data members and only a single virtual function.  Often this virtual function will be operator (), but in the following example I use a function called "Operate" because I think it makes the code easier to read.  

First you need to define a base class, preferabley pure abstract, that defines the virtual function(s).  For example

class MathOperation
{
public:
    virtual int Operate(int x,int y) = 0;
};

Then from this base class derive concrete classes for the differen operations to be performed, like

class Add : pulbic MathOperation
{
public:
    virtual int Operate(int x,int y) { return x + y; };
};

class Sub: pulbic MathOperation
{
public:
    virtual int Operate(int x,int y) { return x -  y; };
};

continues
Opps those functions shoudl all have been declared const.  That makes the class much more "flexible" and useful.  Like

class MathOperation
{
public:
    virtual int Operate(int x,int y) const = 0;
};

Then from this base class derive concrete classes for the differen operations to be performed, like

class Add : pulbic MathOperation
{
public:
    virtual int Operate(int x,int y) const { return x + y; };
};

class Sub: pulbic MathOperation
{
public:
    virtual int Operate(int x,int y) const { return x -  y; };
};

Now to use the class you would declare some code that has a pointer or reference to the base class, but actually works with one of the derived class objects.  For example  you could declare a function that takes a reference to the base class, but is passed one of the derived classes,  This funciton would call the functor's virtual function to perform some sort of action, for example

int DoMath(const MathOperation &Fun)
{
   return Fun.Operate(5,3);
};

this function could be invoiked using an object of either of the derived types.  You could create the objects as locals or globals, but since the virtual function is constant and the DoMath() procedure takes a constant reference parameter, you can simply call DoMath() using an unamed tempoaray, like

int Result = DoMath(Add()); // 5+3

Obviously you can use pointers and references to these functor objects to pass them around and to save them just like function pointers.

Let me know if you have any questions.
Avatar of Xertunus

ASKER

Quite nice, but I want to do something like this:

RightButtonFunction = ShowPopupMenu();

OnRightButton()
{
        Run(RightButtonFunction);
}

(I hope you understand what I mean)
Either approach I showed you will do that.