Function pointers
来源:互联网 发布:mac怎么清理qq缓存 编辑:程序博客网 时间:2024/05/29 14:58
Function pointers are an advanced topic, and this section can be safely skipped or skimmed by those only looking for C++ basics.
In the lesson on pointers, you learned that a pointer is a variable that holds the address of another variable. Function pointers are similar, except that instead of pointing to variables, they point to functions!
Consider the case of an array:
int
nArray[10];
As you now know, nArray is actually a constant pointer to a 10 element array. When we dereference the pointer (either by*nArray
or nArray[nIndex]
), the appropriate array element is returned.
Now consider the following function:
int
foo();
If you guessed that foo is actually a constant pointer to a function, you are correct. When a function is called (via the () operator), the function pointer is dereferenced, and execution branches to the function.
Just like it is possible to declare a non-constant pointer to a variable, it’s also possible to declare a non-constant pointer to a function. The syntax for doing so is one of the ugliest things you will ever see:
// pFoo is a pointer to a function that takes no arguments and returns an integer
int
(*pFoo) ();
The parenthesis around *pFoo are necessary for precedence reasons, as int *pFoo()
would be interpreted as a function named pFoo that takes no parameters and returns a pointer to an integer.
In the above snippet, pFoo is a pointer to a function that has no parameters and returns an integer. pFoo can “point” to any function that matches this signature.
Assigning a function to a function pointer
There are two primary things that you can do with a pointer to a function. First, you can assign a function to it:
int
foo()
{
}
int
goo()
{
}
int
main()
{
int
(*pFoo)() = foo;
// pFoo points to function foo()
pFoo = goo;
// pFoo now points to function goo()
return
0;
}
One common mistake is to do this:
pFoo = goo();
This would actually assign the return value from a call to function goo() to pFoo, which isn’t what we want. We want pFoo to be assigned to function goo, not the return value from goo(). So no parenthesis are needed.
Note that the signature (parameters and return value) of the function pointer must match the signature of the function. Here is an example of this:
// function prototypes
int
foo();
double
goo();
int
hoo(
int
nX);
// function pointer assignments
int
(*pFcn1)() = foo;
// okay
int
(*pFcn2)() = goo;
// wrong -- return types don't match!
double
(*pFcn3)() = goo;
// okay
pFcn1 = hoo;
// wrong -- pFcn1 has no parameters, but hoo() does
int
(*pFcn3)(
int
) = hoo;
// okay
Calling a function using a function pointer
The second thing you can do with a function pointer is use it to actually call the function. There are two ways to do this. The first is via explicit dereference:
int
foo(
int
nX)
{
}
int
(*pFoo)(
int
) = foo;
// assign pFoo to foo()
(*pFoo)(nValue);
// call function foo(nValue) through pFoo.
The second way is via implicit dereference:
int
foo(
int
nX)
{
}
int
(*pFoo)(
int
) = foo;
// assign pFoo to foo()
pFoo(nValue);
// call function foo(nValue) through pFoo.
As you can see, the implicit dereference method looks just like a normal function call — which is what you’d expect, since normal function names are pointers to functions anyway! However, some older compilers do not support the implicit dereference method, but all modern compilers should.
Why use pointers to functions?
There are several cases where pointers to function can be of use. One of the most common is the case where you are writing a function to perform a task (such as sorting an array), but you want the user to be able to define how a particular part of that task will be performed (such as whether the array is sorted in ascending or descending order). Let’s take a closer look at this problem as applied specifically to sorting, as an example that can be generalized to other similar problems.
All sorting algorithms work on a similar concept: the sorting algorithm walks through a bunch of numbers, does comparisons on pairs of numbers, and reorders the numbers based on the results of those comparisons. Consequently, by varying the comparison (which can be a function), we can change the way the function sorts without affecting the rest of the sorting code.
Here is our selection sort routine from a previous lesson:
void
SelectionSort(
int
*anArray,
int
nSize)
{
using
namespace
std;
for
(
int
nStartIndex= 0; nStartIndex < nSize; nStartIndex++)
{
int
nBestIndex = nStartIndex;
// Search through every element starting at nStartIndex+1
for
(
int
nCurrentIndex = nStartIndex + 1; nCurrentIndex < nSize; nCurrentIndex++)
{
// Note that we are using the user-defined comparison here
if
(anArray[nCurrentIndex] < anArray[nBestIndex])
// COMPARISON DONE HERE
nBestIndex = nCurrentIndex;
}
// Swap our start element with our best element
swap(anArray[nStartIndex], anArray[nBestIndex]);
}
}
Now, let’s replace that comparison with a function to do the comparison. Because our comparison function is going to compare two integers and return a boolean value, it will look something like this:
bool
Ascending(
int
nX,
int
nY)
{
return
nY > nX;
}
And here’s our selection sort routine using the Ascending() function to do the comparison:
void
SelectionSort(
int
*anArray,
int
nSize)
{
using
namespace
std;
for
(
int
nStartIndex= 0; nStartIndex < nSize; nStartIndex++)
{
int
nBestIndex = nStartIndex;
// Search through every element starting at nStartIndex+1
for
(
int
nCurrentIndex = nStartIndex + 1; nCurrentIndex < nSize; nCurrentIndex++)
{
// Note that we are using the user-defined comparison here
if
(Ascending(anArray[nCurrentIndex], anArray[nBestIndex]))
// COMPARISON DONE HERE
nBestIndex = nCurrentIndex;
}
// Swap our start element with our best element
swap(anArray[nStartIndex], anArray[nBestIndex]);
}
}
In order to let the caller decide how the sorting will be done, instead of using our own hard-coded comparison function, we’ll allow the caller to provide his own sorting function! This is done via a function pointer.
Because the caller’s comparison function is going to compare two integers and return a boolean value, a pointer to such a function would look something like this:
bool
(*pComparison)(
int
,
int
);
So, we’ll allow the caller to pass our sort routine a pointer to their desired comparison function as the third parameter, and then we’ll use the caller’s function to do the comparison.
Here’s a full example of a selection sort that uses a function pointer parameter to do a user-defined comparison, along with an example of how to call it:
#include <algorithm> // for swap
// Note our user-defined comparison is the third parameter
void
SelectionSort(
int
*anArray,
int
nSize,
bool
(*pComparison)(
int
,
int
))
{
using
namespace
std;
for
(
int
nStartIndex= 0; nStartIndex < nSize; nStartIndex++)
{
int
nBestIndex = nStartIndex;
// Search through every element starting at nStartIndex+1
for
(
int
nCurrentIndex = nStartIndex + 1; nCurrentIndex < nSize; nCurrentIndex++)
{
// Note that we are using the user-defined comparison here
if
(pComparison(anArray[nCurrentIndex], anArray[nBestIndex]))
// COMPARISON DONE HERE
nBestIndex = nCurrentIndex;
}
// Swap our start element with our best element
swap(anArray[nStartIndex], anArray[nBestIndex]);
}
}
// Here is a comparison function that sorts in ascending order
// (Note: it's exactly the same as the previous Ascending() function)
bool
Ascending(
int
nX,
int
nY)
{
return
nY > nX;
}
// Here is a comparison function that sorts in descending order
bool
Descending(
int
nX,
int
nY)
{
return
nY < nX;
}
// This function prints out the values in the array
void
PrintArray(
int
*pArray,
int
nSize)
{
for
(
int
iii=0; iii < nSize; iii++)
cout << pArray[iii] <<
" "
;
cout << endl;
}
int
main()
{
using
namespace
std;
int
anArray[9] = { 3, 7, 9, 5, 6, 1, 8, 2, 4 };
// Sort the array in descending order using the Descending() function
SelectionSort(anArray, 9, Descending);
PrintArray(anArray, 9);
// Sort the array in ascending order using the Ascending() function
SelectionSort(anArray, 9, Ascending);
PrintArray(anArray, 9);
return
0;
}
- Function Pointers
- Function Pointers
- Function pointers
- Pointers to Function, ++
- Abstraction and function pointers
- Pointers to Function
- 函数指针(Function Pointers)
- Programs as Data: Function Pointers
- Example Uses of Function Pointers
- Function Pointers, Functors, Virtual Functions
- Item 14. 函数指针(Function Pointers)
- CallBack function from Pointers on C
- Programs as Data: Function Pointers(函数指针)
- Function Pointers and Callbacks in C
- Function Pointers<外文转载>http://www.learncpp.com/cpp-tutorial/78-function-pointers/
- Member Function Pointers and the Fastest Possible C++ Delegates
- [ZT]Member Function Pointers and the Fastest Possible C++ Delegates
- Member Function Pointers and the Fastest Possible C++ Delegates
- Cocos2dx 3.0 提高篇(十一) xml文档的读取与调用
- Python3.X版本中tkFont到tkinter.font的转变
- Java正则表达式
- UIView的autoresizingMask的详细研究
- Java正则表达式
- Function pointers
- js原型、继承
- The iostream library
- Spring--Quartz 任务调度的配置详解
- Opengl 来给三角形一点颜色看看
- ckeditor使用
- js prototype原型面向对象编程详解
- BOJ407 Blocks
- Linux 下C语言简单实现线程池