Function Pointers and Classes

Hi

I'm trying to implement a class in order to use function pointers to replace the previous enum-switch structure. This has been done by embedding the function pointer as part of the constructor.

I think I have the right code for the header and source files, but I don't know how to create an instance of the modified class as the function the function pointer points to is not a member function of the class.

For reference, the code is:

Header
======

class PayOff
{
public:

PayOff(double Strike_, double (*FunctionPtr) (double, double));
double operator()(double Spot) const;

private:

double Strike;
double (*FunctionPtr) (double, double);

};

Source
======

PayOff::PayOff(double Strike_, double (*FunctionPtr) (double, double))
: Strike(Strike_)
{
FunctionPtr = FunctionPtr;
}

double PayOff::operator()(double Spot) const
{
return FunctionPtr(Spot, Strike);
}

double call(double Spot, double Strike)
{
return max(Spot - Strike, 0);
}

double put(double Spot, double Strike)
{
return max(Strike - Spot, 0);
}

So where previously the enum-switch structure allowed me to create an instance of PayOff with

PayOff callPayOff(Strike, call); as call is a defined enum data type.

How do I create an instance of PayOff with the function pointer structure?

eg. PayOff callPayOff(Strike, &call); doesn't work as call() is kept to be not a member function of PayOff to be consistent with the Open-Closed Principle.

Many thanks
closed account (D80DSL3A)
I found 2 problems with your code.

1) Using the same name for the parameter and the function member (FunctionPtr) in the constructor caused the function pointer to be uninitialized. Changing the argument name to _FunctionPtr fixed this.

2) The 2nd argument is wrong in PayOff callPayOff(Strike, &call);. The address of a function is given by the functions name. Omit the & in &call. Use PayOff callPayOff(Strike, call); instead.

Also, you must declare the function max() somewhere before defining the call() and put() functions since they both call max().

With those fixes I found that your code works fine.
fun2code, many thanks for this.

I think I've made the changes as you've suggested - it this right as below?

Re max(), I've included <minmax.h> from the standard library.

For 2) I've omitted the '&' so that when I create the instance of PayOff, it reads:

PayOff callPayOff(Strike, call);

But the compiler is still saying that 'call' is an undeclared identifier, or if I use 'PayOff::call', call is not a member function of PayOff.

I note that I have created the PayOff instance in main(), which is in a separate file to PayOff1.h and PayOff1.cpp. Does this make a difference? What am I missing?

Amended code for reference:

Header
=====

class PayOff
{
public:

PayOff(double Strike_, double (*FunctionPtr_) (double, double));
double operator()(double Spot) const;

private:

double Strike;
double (*FunctionPtr) (double, double);
};

Source
=====

PayOff::PayOff(double Strike_, double (*FunctionPtr_) (double, double))
: Strike(Strike_)
{
FunctionPtr = FunctionPtr;
}

double PayOff::operator()(double Spot) const
{
return FunctionPtr(Spot, Strike);
}

double call(double Spot, double Strike)
{
return max(Spot - Strike, 0);
}

double put(double Spot, double Strike)
{
return max(Strike - Spot, 0);
}

Interface
=====

int main()
{
/* ... */

PayOff callPayOff(Strike, call);

/* ... */

}
closed account (D80DSL3A)
I've found 2 remaining problems.

1) You have put the definition of the call() in the PayOff.cpp file but did not put a prototype in PayOff.h. The function will not be recognized in main() even if you have included the line
#include "PayOff.h" in the main file. Just as with the member functions you need to put the function prototype in the .h file and the definition in the .cpp file.

2) The assignment in the constructor FunctionPtr = FunctionPtr;. I didn't see this at first. When I fixed the compile errors the program ran but CRASHED. FunctionPtr is still uninitialized in that line. It needs to be FunctionPtr = FunctionPtr_;.

I would put the definitions for the call() and put() functions in the main file since they are not PayOff class member functions, but it still works if placed in the PayOff class files.
I have your code working. Here is exactly what I have:

PayOff.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class PayOff
{
public:

PayOff(double Strike_, double (*FunctionPtr_) (double, double));
double operator()(double Spot) const;

private:

double Strike;
double (*FunctionPtr) (double, double);
};

// non-member functions
double call(double Spot, double Strike);
double put(double Spot, double Strike);

PayOff.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "PayOff.h"

PayOff::PayOff(double Strike_, double (*FunctionPtr_) (double, double))
: Strike(Strike_)
{
FunctionPtr = FunctionPtr_;
}

double PayOff::operator()(double Spot) const
{
return FunctionPtr(Spot, Strike);
}

double call(double Spot, double Strike)
{
return Spot - Strike;
}

double put(double Spot, double Strike)
{
return Strike - Spot;
}

main.cpp
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include "PayOff.h"
using namespace std;

int main()
{
    PayOff pf(5, call);
    cout << pf(7) << endl;// output: 2

    return 0;
}

I removed the calls to the max() because my compiler cannot find any minmax.h file.
Thanks for your help. I've learnt quite a bit.

closed account (z05DSL3A)
It would be good to look at using typedef...
1
2
3
typedef double (*FunctionPtr) (double, double)
//...
PayOff::PayOff(double Strike_, FunctionPtr ptr)
Ah thanks, what are the benefits of using typedef? (Sorry, if it wasn't already apparent I'm a complete newbie)
closed account (z05DSL3A)
The main benefit it it makes things easier.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>


using namespace std;

bool testFunct1(){cout << "Test 1" << endl; return true;}
bool testFunct2(){cout << "Test 2" << endl; return true;}
bool testFunct3(){cout << "Test 3" << endl; return true;}

typedef bool (*TestFuncT_ptr)();

class TestManager
{
public:
    // It is easy to declare a function that  receive function pointers 
    void AddTestAtIndex(TestFuncT_ptr ptr, int index)
    {
        test_functions[index] = ptr;
    }

    // It is easy to declare a function that returns function pointers
    TestFuncT_ptr GetTestAtIndex(int index)
    {
        return test_functions[index];
    }

    void RunTests()
    {
        for(int index = 0; index < 3;++index)
        {
            test_functions[index]();
        }
    }
private:
    // It is easy to have an array of function pointers
    TestFuncT_ptr test_functions[3];
};

int main(int argc, char *argv[])
{
    TestManager tm;

    tm.AddTestAtIndex(testFunct1,0);
    tm.AddTestAtIndex(testFunct2,1);
    tm.AddTestAtIndex(testFunct3,2);

    tm.RunTests();

    // It is easy to declare a function pointers
    TestFuncT_ptr ptr;
    ptr = tm.GetTestAtIndex(0);
    ptr();

    return EXIT_SUCCESS;
}
NB: Untested code...but should be fine.

Oh wow, that's really good.

At line 39, what does "int argc, char *argv[]" do?

At line 52, what does "ptr()" do?
I tried implementing typedef but I don't think I am understanding how initialisation works (or at least I think the issue is initialisation).

The code below compiles but it crashes the moment operator() uses functionPtr.

If I initialise with a different name other than functionPtr (eg. say functionPtr = fPtr), it doesn't compile as fPtr is undefined.

Header
=====
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PayOff
{
public:

	typedef double (*FunctionPtr) (double, double);
	PayOff(double Strike_, FunctionPtr functionPtr);
	double operator()(double Spot) const;

private:
	
	double Strike;
	FunctionPtr functionPtr;

};


Source
=====
1
2
3
4
5
6
7
8
9
10
PayOff::PayOff(double Strike_, FunctionPtr functionPtr)
	: Strike(Strike_) 
{
	functionPtr = functionPtr;
}

double PayOff::operator()(double Spot) const
{
	return functionPtr(Spot, Strike);
}

ok this is starting to sink in now, I was getting confused with what was getting initialised with what (really shouldn't name everything functionPtr!)

Source
======
1
2
3
4
5
6
7
8
9
10
PayOff::PayOff(double Strike_, FunctionPtr fPtr)
	: Strike(Strike_) 
{
	functionPtr = fPtr;
}

double PayOff::operator()(double Spot) const
{
	return functionPtr(Spot, Strike);
}
closed account (z05DSL3A)
Sorry for the slow responses (must be in a totally different time zone).

At line 39, what does "int argc, char *argv[]" do?
That is how command line parameters are passed into the program. It is force of habit that I write my main like int main(int argc, char *argv[]).

At line 52, what does "ptr()" do?
it calls the function that is pointed to by ptr. As the function takes no parameters, there is no arguments in the parenthesis (and I'm not doing anything with the return value).

ok this is starting to sink in now, I was getting confused with what was getting initialised with what (really shouldn't name everything functionPtr!)
It does get fun when you are trying to name a type, variable and parameter. There are ways to use the same name for the member data and the parameter but that is probably best left for another time (read around scope and scope resolution).
no, thanks for replying at all (I'm in Sydney)

just so I understand, so
int argc, char *argv[]

isn't actually necessary for the above program to run?

Otherwise why is it a good habit to write
int main (int argc, char *argv[]
?

thanks for the guidance on the reading
closed account (z05DSL3A)
so int argc, char *argv[] isn't actually necessary for the above program to run?

No it isn't required for it to run. When I said it was a habit I was not meaning to suggest that it is a good habit to get into, just that I nearly always write programs that use command line parameters to set various things so I just end up typing the full version of main.
Topic archived. No new replies allowed.