2.1 函数指针的定义
2.2 调用约定
2.3 给函数指针赋地址值
2.4 函数指针的比较
2.5 用函数指针调用函数
2.6 怎样将函数指针作为参数传递?
2.7 怎样将函数指针作为返回值?
2.8 怎样使用函数指针数组?
第二章 C和C++函数指针的语法
从语法角度讲,有两种类型的函数指针:一种是指向普通C函数或静态C++成员函数,一种是指向非静态C++成员函数。两种根本的区别是非静态的成员函数需要一个隐藏的参数:指向一个类实例的this-pointer。记住:这两种函数指针彼此不兼容。
2.1函数指针的定义
由于函数指针仅仅就是一个变量,所有也必须像其他变量一样被定义。下面的例子我们定义两个函数指针:pt2Function和pt2Member。它们指向的函数有一个float和两个char型参数,返回int型。在C++的例子中,我们假定我们的指针指向的函数是TMyClass的成员函数。
//2.1 define a function pointer
int (*pt2Function) (float, char, char); // C
int (TMyClass::*pt2Member) (float, char, char); // C++
2.2 调用约定(calling convention)
正常情况下你不必去考虑一个函数的调用约定:如果你没有明确另一个调用约定,编译器默认为__cdecl。如果你想知道更多,继续读下去…… 调用约定告诉编译器包括怎样传递参数(从左传、从右传等),怎样生成函数名。调用约定有:__stdcall,__pascal,__fastcall等。调用约定是函数签名的一部分:因此调用约定不同的函数、函数指针之间彼此不兼容。在返回值和函数(或函数指针)名之间指定一种调用约定。
2.3给函数指针赋地址值
给一个函数指针赋一个函数地址相当容易。你只需带一个合适的且已知的函数名或成员函数名即可。可选择的在函数名的前面加地址操作符&。注意:完整的成员函数名需要包括类名以及范围分隔符(::)。同时你需要确保在你对赋值的函数有操作的权限。
//2.3 assign an address to the function pointer
//C
int DoIt(float a, char b, char c) { printf(“DoIt/n”); return a+b+c;}
int DoMore(float a, char b, char c) { printf(“DoMore/n”); return a-b+c;}
pt2Function = DoMore; //assignment
pt2Function = &DoIt; //alternative using address operator
//C++
Class TMyClass
{
Public:
int DoIt(float a, char b, char c) { cout<<“TMyClass ::DoIt”<<endl; return a+b+c;}
int DoMore(float a, char b, char c)
{ cout<<“TMyClass :: DoMore”<<endl; return a-b+c;}
/*more of TMyClass */
};
pt2Member = TMyClass:: DoIt; //assignment
pt2Member = &TMyClass:: DoMore; //alternative using address operator
2.4函数指针的比较
你可以使用比较操作符(==)实现函数指针与函数指针(或与函数)的比较。下面例子来检测pt2Function和pt2Member是否包含了DoIt和&TMyClass:: DoMore的函数地址。如果相等就会打印出来。
//2.4 compare function pointers to functions
//C
if(pt2Function == &DoIt)
printf(“pointer points to DoIt/n”);
//C++
if(pt2Member == &TMyClass:: DoMore)
cout<<“pointer points to TMyClass :: DoMore”<<endl;
2.5用函数指针调用函数
在C中你有两种方法来用函数指针调用函数:可以简单的用函数指针名代替函数名,或者显式来引用它。在C++中由于要有一个类实例来调用非静态成员函数,所以需注意一下。成员函数间调用你可以使用this指针。
//2.5 calling a function using a function pointer
Int result1 = pt2Function (12, ‘a’, ‘b’); //C short way
Int result2 = (*pt2Function) (12, ‘a’, ‘b’); //C
TMyClass instance;
Int result3 = (instance.*pt2Member) (12, ‘a’, ‘b’); //C++
Int result4 = (*this.*pt2Member) (12, ‘a’, ‘b’); //C++ if this-pointer can be used
2.6怎样将函数指针作为参数传递?
你可以将函数指针作为函数的参数。如果你想给回调函数传递指针时会用到这个。下面的例子会展示如何传递一个返回值为int,有1 float 2 char参数的函数指针。
//-------------------------------------------------------------------------------------------------------
//2.6 How to pass a Function Pointer
//<pt2Func> is a pointer to a function which returns an int and takes a float and two
//char
Void PassPtr(int (*pt2Func)(float, char, char))
{
Float result = pt2Func(12, ‘a’, ‘b’); //call using function pointer
Cout<<result<<endl;
}
//execute example code - ‘DoIt’ is a suitable function like defined above in 2.1-4
Void Pass_A_Function_Pointer()
{
Cout<<endl<<”Executing ‘Pass_A_Function_Pointer’”<<endl;
PassPtr(&DoIt);
}
2.7怎样将函数指针作为返回值?
可能有点诡异,但函数指针确实可以作为函数的返回值。下面的例子展示两种方法来返回一个返回值为float,有1 float 2 char参数的函数指针。如果你想返回一个成员函数的函数指针,你需改变所有函数指针的声明、定义。
//----------------------------------------------------------------------------------------------------
//2.7 How to Return a Function Pointer
// ‘Plus’ and ‘Minus’ are defined above in 2.1-4. They return a float and take two float
//direct solution
//function takes a char and returns a pointer to a function which is taking two floats and returns //a float . <opCode> specifies which function to return
Float (*GetPtr1(const char opCode))(foat, float)
{
If(opCode == ‘+’ ) return &Plus;
If(opCode == ‘-’ ) return &Minus;
}
//solution using a typedef
//define a pointer to a function which is taking two floats and returns a float .
Typedef float(*pt2Func)(float, float);
//function takes a char and returns a function Pointer which is defined as a type above . <opCode> //specifies which function to return
Pt2Func GetPtr2(const char opCode)
{
If(opCode == ‘+’ ) return &Plus;
If(opCode == ‘-’ ) return &Minus;
}
//execute example code
Void Return_A_Function_Pointer()
{
Cout<<endl<<”Executing ‘Return_A_Function_Pointer’”<<endl;
Float (*pt2Funtion)(float, float); //define a function pointer
Pt2Function = GetPtr1(‘+’); //get function pointer from function ‘GetPtr1’
Cout<<pt2Function(2, 4)<<endl; //call function using the pointer
Pt2Function = GetPtr1(‘-’); //get function pointer from function ‘GetPtr1’
Cout<<pt2Function(2, 4)<<endl; //call function using the pointer
}
2.8怎样使用函数指针数组?
使用函数指针数组是非常有趣的。它提供了使用index(下标)来选择函数的方法。由于语法较为复杂,经常使人混乱。
//-------------------------------------------------------------------------------------------------------
//2.8 How to Use Arrays of C Function Pointers
//C
//type-definition :’pt2Function’ now can be used as type
typedef int (*pt2Function)(float, char, char);
//illustrate how to work with an array of function pointers
Void Array_Of_Function_Pointers()
{
Printf(“Executing ‘Array_Of_Function_Pointers’/n”);
//<funcArr> is an array with 10 pointers to functions which return an int
// and take a float and two char
pt2Function funcArr[10];
//assign the function’s address - ‘DoIt’ and ‘DoMore’ are suitable functions
//like defined above in 2.1-4
funcArr[0] = &DoIt;
funcArr[1] = &DoMore;
/*more assignments*/
//calling a function using an index to address the function pointer
Printf(“%d/n”, funcArr[1](12, ‘a’, ‘b’));
Printf(“%d/n”, funcArr[0](12, ‘a’, ‘b’));
}
//C++
//type-definition :’pt2Member’ now can be used as type
typedef int (TMyClass::*pt2Member)(float, char, char);
//illustrate how to work with an array of function pointers
Void Array_Of_Function_Pointers()
{
Cout<<end<<“Executing ‘Array_Of_Function_Pointers’”<<endl;
//<funcArr> is an array with 10 pointers to functions which return an int
// and take a float and two char
pt2Member funcArr[10];
//assign the function’s address - ‘DoIt’ and ‘DoMore’ are suitable functions
//like defined above in 2.1-4
funcArr[0] = & TMyClass ::DoIt;
funcArr[1] = & TMyClass ::DoMore;
/*more assignments*/
//calling a function using an index to address the member function pointer
TMyClass instance;
Cout<<( instance.* funcArr[1])(12, ‘a’, ‘b’)<<endl;
Cout<<( instance.* funcArr[0])(12, ‘a’, ‘b’)<<endl;
}