Link to home
Start Free TrialLog in
Avatar of jassi
jassi

asked on

where are Pointers to function used

What is the use of Function Pointers and where are these used ?
Is it considered a good programming practise to use these or
are these to be avoided ?
ASKER CERTIFIED SOLUTION
Avatar of Answers2000
Answers2000

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 Answers2000
Answers2000

A function pointer is a variable that holds an address of a function

What this means is that a function (say function-A) can decide which function to call at runtime (example:whether to call function-B or function-C)

There are many reasons why you may need this behaviour. Here are some examples:

1. A library routine supplies an algorithm, but doesn't provide the data.  The code that calls the library routine provides the data - through a function that provides it.

Example:
qsort - in the C Standard library

qsort provides a function to sort a block of memory of memory using the Quick Sort Algorithm.  It assumes the (a) the data is a continuous block of memory, and (b) each item to be sorted is a continuous block -  but makes no other significant assumption.

However the function that calls qsort - may wish to sort ints, strings, or some user-defined record type (example: a user defined struct).  Obviously the compiler/library author can't know before hand how you might use this function.  Therefore the caller is responsible for providing a function to compare the items to be sorted.  The caller provides a function pointer - also known as a call-back function - to the function to compare 2 elements.

Incidentally it is arguable that the qsort C library function could be even further improved by removing the assumptions about the  memory layout (this isn't what the ANSI C standard says, but if you wrote your own version of this function you might decide to do it) - if you provide a 2nd function pointer parameter - to the function to swap 2 elements (this way a caller can provide functions for compare and swap, and use the same underlying algorithm for memory, disk files, or whatever).


You can use the same principle as this entirely within your own programs - to reuse algorithms with multiple data types.


2.  A library routine provides an unknown known amount of data

Example: Windows provides many "enumeration" functions, e.g. EnumWindows

EnumWindows provides a list of windows matching some criteria

The list size may be variable (it may contain 1 item or 1000)

Rather than provide a fixed size array, and rather than make complex assumptions about clean up (e.g. if EnumWindows were to allocate memory for the list who would be responsible for the cleanup - the caller or Windows ?) - INSTEAD you provide a caller back function (a function pointer).  EnumWindows simply calls this function once for each window that matches it's search criteria.  The call-back function can then do whatever it wants over an extended period.


3. Information/Notification over an extended period.

The system, a library routine, or part of your program, needs to tell another piece of code that something has happened (an event or message).  For example windows might need to tell your code whenever the mouse moves over a particular window.  It does this through a function pointer:

- when you create a window - you provide a function pointer to your window's code (in MS Windows this is called a WndProc)
- whenever a message needs to be sent to your code telling it something has happened - Windows calls your code and says - the mouse has moved, the keyboard was used, or whatever
- your routine can then decide how to handle this.


4. Use of functions as data & polymorphism

In C you might have an array of shapes on the screen.  Each shape is represented by a set of bounding coords (say a bouding rectangle) and some function to draw the shape.  If a user-defined struct includes a pointer to a function to draw the shape, you can manipulate the array (example:sort it, delete elements) as data.  Polymorphism basically means common behaviour across all shapes (more on this in my C++ comment below) - example: all shapes include a function pointer to a "DrawTheShape" function - which is different for each kind of shape (square, ellipse, line, etc.)

Some C++ comments below
>> Is it considered a good programming practise to use these

It is considered good programming practisre to use these - **when** they need to be used.  Like anything else - it is good only when appropriate.

For some code, (#1 and #3 above)  there is no practical alternative in C.  For some code - it is considered good programming practise if it meets your design goals (which may be clarity, performance etc.)

It is simply a tool use it well.

Function Pointers can be tricky, so it is easy to make mistakes.

C++ offers some alternatives - see my next & last comment
C++ offers 2 alternatives to function pointers

A. Template classes & functions


Templates are not an exact alternative to function pointers, but can solve many of the same problems, without being so tricky (they have _different_ tricks).  Basically the template provides an outline for an algorithm, but can leave out things like data-type, and this is filled in, when code is used.

Example: part of the C++ standard library (STL = standard template library).  Provides a sort routine (called "sort".  The coding call it provides the data.  The template makes some assumptions about the operations available on the data provided (example: items can be compared) - but only minimal assumptions.  In the case of the "sort" routine it can do whatever Q sort can.

This is mainly an alternative way of doing #1 from my original comment,

Templates can also do additional stuff



B. Virtual functions.

This is the C++ way of doing function pointers (you can still use C style function pointers too).

If you pass a pointer to class containing a virtual or pure virtual function, this is equivalent to passing a function pointer, but is type safe (the compiler checks better so you are less likely to make errors).

Example - library might define (it doesn't)
class MyQSortBase
{
public:
   virtual int Compare( int i, int j ) const =  0 ; // pure virtual
   virtual void Swap( int i, int j ) = 0 ; // pure virtual
} ;

void MyQSort( int nItemCount, MyQSortBase * pUserClass ) ;

The caller code then derive a class from MyQSortBase (and actually implement the code to do compare and swap) and pass a pointer to an object to this type to MyQSort to actually do the sort.  This is equivalent to passing 2 function pointers.

Extending this principle, you can solve all the original problems I gave in my comment (using C++) without using function pointers.

In C++ there are still some reasons to use function pointers.
- Different manufacturers C++ compilers are generally not compatible for passing classes/objects.  If you write a library or use somebody else's library, a function pointer instead of a class pointer may be more likely to be compatible with somebody else's code.
- Function pointers may interface easier to other languages (e.g. C or Assembler) - do you want people interfacing to your code to know/care your write C++ including which compiler version
- Function pointers may be part of a legacy standard you don't want to break (e.g. the Windows API)
- Virtual functions may be slightly slower than function pointers.  - in most cases this is probably not a consideration - but may be if called a 1,000,000 times or if in a time critical code section (e.g. port handling)






Oh one final point - the MyQSort function is in the jargon - "Polymorphic".

More commonly in books you'll see this behaviour to manipulate arrays of objects, all of which share some common behaviour

example:
Shapes program referred to in original #4

All shapes - might have a "draw your self" function, and a "show the shapes properties" function - both of which are virtual or pure virtual members of the base class of all shapes
Impressive answer--your fingers must be tired too.

I would just like to add that whenever possible you should use virtual functions instead of function pointers.  You need function pointers only when dealing with code writen by someone else that uses function pointers (like the C sort procedure or the operating system's functions) or if your code must interface with a non-C++ language (Like if it is in a DLL that can be called by programs written in other languages).  For all other cases, that is when writting code that will be used within C++, you should always use virutal functions.  They are much safer and much more powerful.  There is nothing that can be done with a function pointer that can't be done using virtual functions.  (Virtual functions use function pointers in fact, but they allow the compiler to do a lot of safety checking and do a lot of the work for you.)
thanks nietod - i don't think I would have started if I realized what the answer would have grown too!

Good point, but I think i kind of said it (section B in 3:56 comment - para#2) - but no harm in emphasizing the point (or should I said pointer? <g> and <groan> )

Avatar of jassi

ASKER

Thanx a lot Answers2000.... very clear and impressive answer..... wish there was something higher than excellent in the ratings scheme... thanx once again