C++中函数指针的使用
2016-06-19 20:46
549 查看
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:
函数指针是一个指向函数的指针,函数指针表示一个函数的入口地址。指针是变量,所以函数指针也是变量,因此可以使用变量定义的方式来定义函数指针。只是这个指针它不像普通的指针指向一个变量,而它指向的是一个函数,也就是它存储的是一个函数的地址。
在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 optional foo = &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); // 2 return 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 array for (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 smallest if (comparisonFcn(array[smallestIndex], array[currentIndex])) // COMPARISON DONE HERE // This is the new smallest number for this iteration smallestIndex = currentIndex; } // Swap our start element with our smallest element std::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() function selectionSort(array, 9, descending); printArray(array, 9); // 9 8 7 6 5 4 3 2 1 // Sort the array in ascending order using the ascending() function selectionSort(array, 9, ascending); printArray(array, 9); // 1 2 3 4 5 6 7 8 9 return 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 order return 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 9 return 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 add case '+': return add; case '-': return subtract; case '*': return multiply; case '/': return divide; } } int test_function_pointers5() { int x = getInteger(); // 5 char op = getOperation(); // * int y = getInteger(); // 6 arithmeticFcn fcn = getArithmeticFcn(op); std::cout << x << ' ' << op << ' ' << y << " = " << fcn(x, y) << '\n'; // 5 * 6 = 30 return 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 = 30 return 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.905512 return 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 function x = i / 100.0 * (hi - lo) + lo; y = (*funcp)(x); sum += y; } return sum / 101.0; } int test_function_pointers8() { double(*fp)(double); // Function pointer double sum; // Use 'sin()' as the pointed-to function fp = 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 function fp = cos; sum = compute_sum(fp, 0.0, 1.0); printf("sum(cos): %f\n", sum); // sum(cos): 0.840758 return 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 = 8 return 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] = 2 return 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) = 6 std::cout << "Foo::mult(3,5) = " << bar2(3, 5, &foo, &Foo::mult) << std::endl; // Foo::mult(3,5) = 15 std::cout << "Foo::negate(6) = " << bar3(6, &Foo::negate) << std::endl; // Foo::negate(6) = -6 return 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) // 15 fptr[1](5, 4); // two(5, 3) // 20 return 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 params int (Number::*NumberPtr[2])(); NumberPtr[0] = &Number::one; NumberPtr[1] = &Number::two; std::cout << (object.*NumberPtr[0])() << std::endl; // 1 std::cout << (object.*NumberPtr[1])() << std::endl; // 2 return 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 ptr double 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; // 100 one.UpgradeToExperienced(); std::cout << one.Pay(10) << std::endl; // 200 return 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 pointers void(*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); // 1 if (ch > 2) return 0; (*fun_ptr_arr[ch])(a, b); // Subtraction is 5 return 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" pointer static 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); // error fdptr = static_cast<int (Foo_2::*) (char*)> (fptr); // OK: contravariance Bar 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 file strcpy(buff, source); } void Append(char * buff, const char * source){ // extend the file strcat(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]; // target working(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++中函数指针的使用
- 冒泡排序(c语言实现)
- C++指针
- error C2144: 语法错误:“int”的前面应有“;”
- C语言中getchar()和putchar()的实现细节
- I00029 C语言程序-打印九九乘法表
- C语言函数传参汇总
- CSv纯C++解析
- 【C】C语言输入输出缓冲区
- C语言的标准输入输出
- 指针学习路线
- c++DLL编程详解
- C++Primer笔记(一):C++基本数据类型及其取值范围
- 第16周项目2--用文件保存学生的名单
- C++ STL map的使用
- 这是我开通博客的原因;虽然不是什么大问题;关于指针与对象(C++)
- C++中结构体与类的区别
- 基于C的2048游戏
- 为什么在C++中需要虚函数
- 基于POSIX下REGEX库的文本URL过滤(C/C++语言)