函数指针 详解 (第二章 C和C++函数指针的语法)

来源:互联网 发布:程序员在哪里接私活 编辑:程序博客网 时间:2024/05/21 00:46

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;
}