A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior.

函数指针是一个指向函数的指针,函数指针表示一个函数的入口地址。指针是变量,所以函数指针也是变量,因此可以使用变量定义的方式来定义函数指针。只是这个指针它不像普通的指针指向一个变量,而它指向的是一个函数,也就是它存储的是一个函数的地址。

在C中,一个函数指针可以多次赋值。取地址符号是可选的,却是推荐使用的。在C++中,对于赋值必须要加”&”,而且还必须在此之前已经定义好了一个类实例,取地址符号要操作于这个类实例的对应的函数成员上。在使用成员函数的指针调用成员函数时,必须要加类实例的名称,然后再使用.*或者->*来使用成员函数指针。

函数指针没有普通变量指针的算术操作,但是可以进行比较操作。

C语言函数指针的定义形式:返回类型 (*函数指针名称)(参数类型, 参数类型, …);

C++函数指针的定义形式:返回类型 (类名称::*函数成员名称)(参数类型,参数类型, …);

C++中,类的静态成员函数指针和C的指针用法相同,不需要加类名。普通成员函数,一定要加类名。

函数指针一般有两个用途:调用函数和做函数的参数。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include <stdio.h> // for printf
#include <string.h> // for strchr
#include <math.h>
#include <functional>
#include <algorithm> // for std::swap, use <utility> instead if C++11
#include <iostream>
#include "function_pointers.hpp"// reference: http://www.newty.de/fpt/intro.html// reference: http://www.cprogramming.com/tutorial/function-pointers.html
void my_int_func(int x)
{printf("%d\n", x);
}int test_function_pointers1()
{void (*foo)(int);// Initializing Function Pointers:// To initialize a function pointer, you must give it the address of a function in your program.// the ampersand is actually optionalfoo = &my_int_func;// call my_int_func (note that you do not need to write (*foo)(2) )foo(2); // 2// but if you want to, you may (*foo)(2); // 2return 0;
}int int_sorter(const void *first_arg, const void *second_arg)
{int first = *(int*)first_arg;int second = *(int*)second_arg;if (first < second) {return -1;} else if (first == second) {return 0;} else {return 1;}
}int test_function_pointers2()
{int array[10];for (int i = 0; i < 10; ++i) {array[i] = 10 - i;}// void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));qsort(array, 10, sizeof(int), int_sorter);for (int i = 0; i < 10; ++i) {printf("%d\n", array[i]); // 1 2 3 4 5 6 7 8 9 10}return 0;
}// Note our user-defined comparison is the third parameter
void selectionSort(int *array, int size, bool(*comparisonFcn)(int, int))
{// Step through each element of the arrayfor (int startIndex = 0; startIndex < size; ++startIndex) {// smallestIndex is the index of the smallest element we've encountered so far.int smallestIndex = startIndex;// Look for smallest element remaining in the array (starting at startIndex+1)for (int currentIndex = startIndex + 1; currentIndex < size; ++currentIndex) {// If the current element is smaller than our previously found smallestif (comparisonFcn(array[smallestIndex], array[currentIndex])) // COMPARISON DONE HERE// This is the new smallest number for this iterationsmallestIndex = currentIndex;}// Swap our start element with our smallest elementstd::swap(array[startIndex], array[smallestIndex]);}
}// Here is a comparison function that sorts in ascending order
// (Note: it's exactly the same as the previous ascending() function)
bool ascending(int x, int y)
{return x > y; // swap if the first element is greater than the second
}// Here is a comparison function that sorts in descending order
bool descending(int x, int y)
{return x < y; // swap if the second element is greater than the first
}// This function prints out the values in the array
void printArray(int *array, int size)
{for (int index = 0; index < size; ++index)std::cout << array[index] << " ";std::cout << '\n';
}// reference: http://www.learncpp.com/cpp-tutorial/78-function-pointers/
int test_function_pointers3()
{int array[9] = { 3, 7, 9, 5, 6, 1, 8, 2, 4 };// Sort the array in descending order using the descending() functionselectionSort(array, 9, descending);printArray(array, 9); // 9 8 7 6 5 4 3 2 1// Sort the array in ascending order using the ascending() functionselectionSort(array, 9, ascending);printArray(array, 9); // 1 2 3 4 5 6 7 8 9return 0;
}bool evensFirst(int x, int y)
{// if x is even and y is odd, x goes first (no swap needed)if ((x % 2 == 0) && !(y % 2 == 0))return false;// if x is odd and y is even, y goes first (swap needed)if (!(x % 2 == 0) && (y % 2 == 0))return true;// otherwise sort in ascending orderreturn ascending(x, y);
}int test_function_pointers4()
{int array[9] = { 3, 7, 9, 5, 6, 1, 8, 2, 4 };selectionSort(array, 9, evensFirst);printArray(array, 9); // 2 4 6 8 1 3 5 7 9return 0;
}int getInteger()
{std::cout << "Enter an integer: ";int x;std::cin >> x;return x;
}char getOperation()
{char op;do {std::cout << "Enter an operation ('+', '-', '*', '/'): ";std::cin >> op;} while (op != '+' && op != '-' && op != '*' && op != '/');return op;
}int add(int x, int y)
{return x + y;
}int subtract(int x, int y)
{return x - y;
}int multiply(int x, int y)
{return x * y;
}int divide(int x, int y)
{return x / y;
}typedef int(*arithmeticFcn)(int, int);arithmeticFcn getArithmeticFcn(char op)
{switch (op) {default: // default will be to addcase '+': return add;case '-': return subtract;case '*': return multiply;case '/': return divide;}
}int test_function_pointers5()
{int x = getInteger(); // 5char op = getOperation(); // *int y = getInteger(); // 6arithmeticFcn fcn = getArithmeticFcn(op);std::cout << x << ' ' << op << ' ' << y << " = " << fcn(x, y) << '\n'; // 5 * 6 = 30return 0;
}struct arithmeticStruct
{char op;arithmeticFcn fcn;
};static arithmeticStruct arithmeticArray[] {{ '+', add },{ '-', subtract },{ '*', multiply },{ '/', divide }
};arithmeticFcn getArithmeticFcn_(char op)
{for (auto &arith : arithmeticArray) {if (arith.op == op)return arith.fcn;}return add; // default will be to add
}int test_function_pointers6()
{int x = getInteger();char op = getOperation();int y = getInteger();arithmeticFcn fcn = getArithmeticFcn_(op);std::cout << x << ' ' << op << ' ' << y << " = " << fcn(x, y) << '\n'; // 5 * 6 = 30return 0;
}double cm_to_inches(double cm)
{return cm / 2.54;
}// reference: https://en.wikipedia.org/wiki/Function_pointer
int test_function_pointers7()
{double(*func1)(double) = cm_to_inches;printf("%f\n", func1(15.0)); // 5.905512return 0;
}// Function taking a function pointer as an argument
double compute_sum(double(*funcp)(double), double lo, double hi)
{double  sum = 0.0;// Add values returned by the pointed-to function '*funcp'for (int i = 0; i <= 100; i++) {double  x, y;// Use the function pointer 'funcp' to invoke the functionx = i / 100.0 * (hi - lo) + lo;y = (*funcp)(x);sum += y;}return sum / 101.0;
}int test_function_pointers8()
{double(*fp)(double); // Function pointerdouble  sum;// Use 'sin()' as the pointed-to functionfp = sin;sum = compute_sum(fp, 0.0, 1.0);printf("sum(sin): %f\n", sum); // sum(sin): 0.459308// Use 'cos()' as the pointed-to functionfp = cos;sum = compute_sum(fp, 0.0, 1.0);printf("sum(cos): %f\n", sum); // sum(cos): 0.840758return 0;
}int add_(int first, int second)
{return first + second;
}int subtract_(int first, int second)
{return first - second;
}int operation(int first, int second, int(*functocall)(int, int))
{return (*functocall)(first, second);
}int test_function_pointers9()
{int  a, b;int(*plus)(int, int) = add_;int(*minus)(int, int) = subtract_;a = operation(7, 5, plus);b = operation(20, a, minus);std::cout << "a = " << a << " and b = " << b << std::endl; // a = 12 and b = 8return 0;
}static double derivative(const std::function<double(double)> &f, double x0, double eps)
{double eps2 = eps / 2;double lo = x0 - eps2;double hi = x0 + eps2;return (f(hi) - f(lo)) / eps;
}static double f(double x)
{return x * x;
}int test_function_pointers10()
{double x = 1;std::cout << "d/dx(x ^ 2) [@ x = " << x << "] = " << derivative(f, x, 1e-5) << std::endl; // d/dx(x ^ 2) [@ x = 1] = 2return 0;
}class Foo {public:int add(int i, int j){return i + j;}int mult(int i, int j){return i*j;}static int negate(int i){return -i;}
};int bar1(int i, int j, Foo* pFoo, int(Foo::*pfn)(int, int))
{return (pFoo->*pfn)(i, j);
}typedef int(Foo::*Foo_pfn)(int, int);int bar2(int i, int j, Foo* pFoo, Foo_pfn pfn)
{return (pFoo->*pfn)(i, j);
}typedef int(*PFN)(int);int bar3(int i, PFN pfn)
{return pfn(i);
}int test_function_pointers11()
{Foo foo;std::cout << "Foo::add(2,4) = " << bar1(2, 4, &foo, &Foo::add) << std::endl; // Foo::add(2,3) = 6std::cout << "Foo::mult(3,5) = " << bar2(3, 5, &foo, &Foo::mult) << std::endl; // Foo::mult(3,5) = 15std::cout << "Foo::negate(6) = " << bar3(6, &Foo::negate) << std::endl; // Foo::negate(6) = -6return 0;
}void one(int a, int b) { std::cout << a + b << "\n"; }
void two(int a, int b) { std::cout << a*b << "\n"; }// reference: http://www.dev-hq.net/c++/20--function-pointers
int test_function_pointers12()
{//void(*fptr)(int, int); // Declare a function pointer to voids with two int params//fptr = one; // fptr -> one//fptr(12, 3); // => one(12, 3)//fptr = two; // fptr -> two//fptr(5, 4); // => two(5, 3)void(*fptr[2])(int, int);fptr[0] = one;fptr[1] = two;fptr[0](12, 3); // one(12, 3)  // 15fptr[1](5, 4); // two(5, 3)  // 20return 0;
}class Number
{
public:int i;Number() { i = 0; }int one() { return i + 1; }int two() { return i + 2; }
};int test_function_pointers13()
{Number object; // Create a new 'Number' object named 'object'// Declare a pointer array with two elements which are pointers to member functions in "Number" of type 'int' with takes no paramsint (Number::*NumberPtr[2])();NumberPtr[0] = &Number::one;NumberPtr[1] = &Number::two;std::cout << (object.*NumberPtr[0])() << std::endl; // 1std::cout << (object.*NumberPtr[1])() << std::endl; // 2return 0;
}class Employee
{
public:Employee(){wageCalc = &Employee::CalculateWage; // wageCalc -> CalculateWage}void UpgradeToExperienced(){wageCalc = &Employee::CalculateExperiencedWage; // wageCalc -> CalculateExperiencedWage}double Pay(double hours){return (this->*wageCalc)(hours); // => object.*wageCalc(hours)}private:double (Employee::*wageCalc)(double hours); // The member function ptrdouble CalculateWage(double hours){return 10 * hours;}double CalculateExperiencedWage(double hours){return 20 * hours;}
};int test_function_pointers14()
{Employee one;std::cout << one.Pay(10) << std::endl; // 100one.UpgradeToExperienced();std::cout << one.Pay(10) << std::endl; // 200return 0;
}void add_1(int a, int b)
{printf("Addition is %d\n", a + b);
}
void subtract_1(int a, int b)
{printf("Subtraction is %d\n", a - b);
}
void multiply_1(int a, int b)
{printf("Multiplication is %d\n", a*b);
}// reference: http://www.geeksforgeeks.org/function-pointer-in-c/
int test_function_pointers15()
{// fun_ptr_arr is an array of function pointersvoid(*fun_ptr_arr[])(int, int) = { add_1, subtract_1, multiply_1 };unsigned int ch, a = 15, b = 10;printf("Enter Choice: 0 for add, 1 for subtract and 2 for multiply\n");scanf("%d", &ch); // 1if (ch > 2) return 0;(*fun_ptr_arr[ch])(a, b); // Subtraction is 5return 0;
}class Foo_{
public:int f(std::string str){std::cout << "Foo_::f()" << std::endl;return 1;}
};// reference: http://www.codeguru.com/cpp/cpp/article.php/c17401/C-Tutorial-PointertoMember-Function.htm
int test_function_pointers16()
{int (Foo_::*fptr) (std::string) = &Foo_::f;Foo_ obj;(obj.*fptr)("str");//call: Foo::f() through an object // Foo_::f()Foo_* p = &obj;(p->*fptr)("str");//call: Foo::f() through a pointer // Foo_::f()return 0;
}class Foo_1{
public:// A "static" member function has no "this" pointerstatic int f(std::string str){std::cout << "Foo::f()" << std::endl;return 1;}
};int test_function_pointers17()
{//int (Foo_1::*fptr) (string) = &Foo_1::f; // error int(*fptr) (std::string) = &Foo_1::f; // correct(*fptr)("str"); // call Foo_1::f() // Foo::f()return 0;
}class Foo_2{
public:int f(char* c = 0){std::cout << "Foo_2::f()" << std::endl;return 1;}
};class Bar{
public:void b(int i = 0){std::cout << "Bar::b()" << std::endl;}
};class FooDerived :public Foo_2{
public:int f(char* c = 0){std::cout << "FooDerived::f()" << std::endl;return 1;}
};int test_function_pointers18()
{typedef  int (Foo_2::*FPTR) (char*);typedef  void (Bar::*BPTR) (int);typedef  int (FooDerived::*FDPTR) (char*);FPTR fptr = &Foo_2::f;BPTR bptr = &Bar::b;FDPTR fdptr = &FooDerived::f;// Bptr = static_cast<void (Bar::*) (int)> (fptr); // errorfdptr = static_cast<int (Foo_2::*) (char*)> (fptr); // OK: contravarianceBar obj;(obj.*(BPTR)fptr)(1); // call: Foo_2::f()  // Foo_2::f()return 0;
}class Foo_3{
public:virtual int f(char* c = 0){std::cout << "Foo_3::f()" << std::endl;return 1;}
};class Bar_3{
public:virtual void b(int i = 0){std::cout << "Bar_3::b()" << std::endl;}
};class FooDerived_3 :public Foo_3{
public:int f(char* c = 0){std::cout << "FooDerived_3::f()" << std::endl;return 1;}
};int test_function_pointers19()
{typedef  int (Foo_3::*FPTR) (char*);typedef  void (Bar_3::*BPTR) (int);FPTR fptr = &Foo_3::f;BPTR bptr = &Bar_3::b;FooDerived_3 objDer;(objDer.*fptr)(0); // call: FooDerived::f(), not Foo::f() // FooDerived::f()Bar_3 obj;(obj.*(BPTR)fptr)(1); // call: Bar::b() , not Foo::f() // Bar_3::b()return 0;
}class Printer{ // An abstract printing machine
public:void Copy(char * buff, const char * source){ // copy the filestrcpy(buff, source);}void Append(char * buff, const char * source){ // extend the filestrcat(buff, source);}
};enum OPTIONS { COPY, APPEND }; // two possible commands in the menu.
typedef void(Printer::*PTR) (char*, const char*); // pointer-to-member function void working(OPTIONS option, Printer* machine, char* buff, const char* infostr)
{PTR pmf[2] = { &Printer::Copy, &Printer::Append }; // pointer array switch (option){case COPY:(machine->*pmf[COPY])(buff, infostr);break;case APPEND:(machine->*pmf[APPEND])(buff, infostr);break;}
}int test_function_pointers20()
{OPTIONS option;Printer machine;char buff[40]; // targetworking(COPY, &machine, buff, "Strings ");working(APPEND, &machine, buff, "are concatenated! ");std::cout << buff << std::endl; // Strings are concatenated!return 0;
}// reference: http://www.radmangames.com/programming/how-to-use-function-pointers-in-cplusplus
// 1. Declaring function pointer variables
// (1). Non member functions
// return_type (*varName)() = namespace::function; // no parameters
// return_type(*varName)(paramType1, paramTypeN) = namespace::function;
// (2). Member functions
// return_type (Class::*varName)(paramType1, paramTypeN) = &Class::method;
// (3). Typedefs for function pointer types
// typedef return_type (*TypeName)(paramType1, paramTypeN);
// typedef return_type(ExampleClass::*TypeName)(paramType1, paramTypeN);
// static_cast<void(Class::*)()>(&Class::method)
// 2. Using function pointer variables
// (1). Calling a non-member function pointer
/*
void (*funcPtr)(paramType1, paramTypeN) = namespace::function;
funcPtr(parameter1, parameterN);
*/
// (2). Calling a member function pointer
/*
void (Class::*memberFuncPtr)() = &Class::method;Class* ptrInstance = new Class();
(ptrInstance->*memberFuncPtr)();Class refInstance;
(refInstance.*memberFuncPtr)();
*/namespace
{int simple() { return 0; }float test1(int first, float second, char third) { return 0.0; }float test2(int first, float second, char third) { return 0.0; }template <typename T_Example>void templateExample(T_Example param) {}class Class{public: // interface void method(int var) {}void overload(int var) {}void overload(int first, float second) {}}; // class template <typename T_Example>class TemplateClass{public: // interface void templateDo(T_Example templateParam, int extraParam) {}}; // class } // namespace int test_function_pointers21()
{// non-member examples int(*simpleNonMember)() = simple;simpleNonMember();typedef float(*TestTypeFuncPtr)(int, float, char);TestTypeFuncPtr test1FuncPtr = test1;TestTypeFuncPtr test2FuncPtr = test2;test1(7, 12.5, 'c'); // directly test1FuncPtr(7, 12.5, 'c'); // through the function pointer test2FuncPtr(11, 857.2, 'r');// non-member template examples void(*templateExampleFuncPtr1)(int) = templateExample<int>;void(*templateExampleFuncPtr2)(float) = templateExample<float>;templateExampleFuncPtr1(7);templateExampleFuncPtr2(7.f);// member examples Class* classPtr = new Class();Class classRef;void (Class::*overload2FuncPtr)(int, float) = &Class::overload;(classRef.*overload2FuncPtr)(0, 2.f);typedef void (Class::*ClassIntParamTypeFuncPtr)(int);ClassIntParamTypeFuncPtr overload1AndMethodFuncPtr = nullptr;overload1AndMethodFuncPtr = &Class::method;overload1AndMethodFuncPtr = &Class::overload;(classPtr->*overload1AndMethodFuncPtr)(7);(classRef.*overload1AndMethodFuncPtr)(7);// template class member examples TemplateClass<float>* templateClassPtr = new TemplateClass<float>();typedef void (TemplateClass<float>::*TemplateDoTypeFloat)(float, int);TemplateDoTypeFloat templateDoFuncPtr = &TemplateClass<float>::templateDo;(templateClassPtr->*templateDoFuncPtr)(11.f, 5);return 0;
}

GitHub: https://github.com/fengbingchun/Messy_Test

C++中函数指针的使用相关推荐

  1. 关于C++中函数指针的使用(包含对typedef用法的讨论)

    关于C++中函数指针的使用(包含对typedef用法的讨论) (一)简单的函数指针的应用. //形式1:返回类型(*函数名)(参数表) char (*pFun)(int); char glFun(in ...

  2. C/C++中函数指针的含义(转)

                                 C/C++中函数指针的含义 函数存放在内存的代码区域内,它们同样有地址,我们如何能获得函数的地址呢?如果我们有一个int test(int a ...

  3. C++中函数指针数组的使用

    C++中函数指针数组的使用 来源:电脑教程在线(http://www.linuxdiyf.com/1/) 作者:linux 原文:C++中函数指针数组的使用(http://www.linuxdiyf. ...

  4. 关于C++中函数指针的使用

    关于C++中函数指针的使用(包含对typedef用法的讨论)  (一)简单的函数指针的应用. //形式1:返回类型(*函数名)(参数表)  char (*pFun)(int);  char glFun ...

  5. STC15分时内核中函数指针的使用问题

    2019独角兽企业重金招聘Python工程师标准>>> 基于前后台设计的系统随着功能的递增变得越来越难以维护, 所以决定为STC15F2K单片机编写一个基于时分的非抢占式内核,方便进 ...

  6. C++中函数指针的运用

    /** class_pointer.cxx** Created on: 2012-9-15* Author: Jesse Meng*/#include <iostream> using n ...

  7. 【C/C 】浅谈C/C 中函数指针与回调函数

    01.函数指针 1.1.函数指针定义 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似.我们可以把函数的这个首地址(或称入口地址)赋予 ...

  8. C中函数指针的基本语法和思想

    1.C语言中函数的调用可分为直接调用和间接调用(函数指针),具体调用方法如下: int add(int a,int b) { return a+b; } void main() { add(1,2); ...

  9. C++ 类中函数指针的使用

    文章目录 函数指针用法 类中的成员函数接收函数指针 情况1 情况2 情况3 总结 函数指针用法 函数指针可以作为一个函数的参数,传不同的函数指针给这个函数就可以让其实现不能的功能.从而我们可以复用这个 ...

最新文章

  1. 免费公开课 | AI对抗攻防系列专题,今晚7点第一讲
  2. endnote中科大版区别_研究生科研入门Endnote文献管理软件使用
  3. 高精度倾斜摄影建模解决方案
  4. windows和centos进行文件上传和下载
  5. js 用迭代器模式优雅的处理递归问题
  6. Windows平台下SVN安装配置及使用
  7. Spring AOP方法分析
  8. vs code c语言json文件配置,解析VScode在Windows环境下c_cpp_properties.json文件配置问题(推荐)...
  9. 重装了新版IDEA,但我之前的个人配置全丢了,太烦了!
  10. HM5469A单节锂电池保护IC过流9A电流可以做8W
  11. python123第三次作业的解答
  12. 如何显示Word 左侧目录
  13. java 杨辉三角_Java语言杨辉三角
  14. 怎么关闭win10自带杀毒软件
  15. 电传输之POE供电的介绍
  16. python matplotlib axes3d.get_test_data() 是什么意思?(获得测试数据)
  17. 浅谈未来的人工智能与奇点临近
  18. django Email
  19. 可重入锁详解(什么是可重入)
  20. v-chart 图表曲线图(双曲线)

热门文章

  1. c++中求字符串数组的min/max
  2. YOLOv3学习笔记
  3. c语言大顶堆数组维护,图解大顶堆的构建、排序过程
  4. Python——字符串大小写转化
  5. 基础矩阵,本质矩阵,单应性矩阵讲解
  6. json格式天气数据的获取,jsonp方式获取统计图数据
  7. Maya2022基础入门学习教程
  8. Rocksdb 写入数据后 GetApproximateSizes 获取的大小竟然为0?
  9. 关于ceph源码 backtrace 打印函数调用栈
  10. Babel 相关资料