函数指针

来源:互联网 发布:伊布 知乎 编辑:程序博客网 时间:2024/05/22 07:44

 函数存放在内存的代码区域内,它们同样有地址,我们如何能获得函数的地址呢?

  如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。

  定义一个指向函数的指针用如下的形式,以上面的test()为例:

int (*fp)(int a);//这里就定义了一个指向函数的指针

  函数指针不能绝对不能指向不同类型,或者是带不同形参的函数,在定义函数指针的时候我们很容易犯如下的错误。

int *fp(int a);//这里是错误的,因为按照结合性和优先级来看就是先和()结合,然后变成了一个返回整形指针的函数了,而不是函数指针,这一点尤其需要注意!

  下面我们来看一个具体的例子:

#include <iostream
#include <string
using namespace std; 
 
int test(int a); 
 
void main(int argc,charargv[])   

    cout<<test<<endl;//显示函数地址 
    int (*fp)(int a); 
    fp=test;//将函数test的地址赋给函数学指针fp 
    cout<<fp(5)<<"|"<<(*fp)(10)<<endl; 
//上面的输出fp(5),这是标准c++的写法,(*fp)(10)这是兼容c语言的标准写法,两种同意,但注意区分,避免写的程序产生移植性问题! 
    cin.get(); 

 
int test(int a) 

    return a; 
}

  typedef定义可以简化函数指针的定义,在定义一个的时候感觉不出来,但定义多了就知道方便了,上面的代码改写成如下的形式:

#include <iostream
#include <string
using namespace std; 
 
int test(int a); 
 
void main(int argc,charargv[])   

    cout<<test<<endl; 
    typedef int (*fp)(int a);//注意,这里不是生命函数指针,而是定义一个函数指针的类型,这个类型是自己定义的,类型名为fp 
    fp fpi;//这里利用自己定义的类型名fp定义了一个fpi的函数指针! 
    fpi=test; 
    cout<<fpi(5)<<"|"<<(*fpi)(10)<<endl; 
    cin.get(); 

 
int test(int a) 

    return a; 
}

 

 

用typedef修改atexit()原型

typydef void Exitfunc(void);

int atexit(Exitfun *fp);

 

比如你要声明一个函数,它带一个int参数,然后返回一个函数指针,指针类型为void (*)(int*, int, char); 函数的名字叫foo,怎么写呢,如果不用typedef,的确有点麻烦,像这样:
void (*foo(int))(int*, int, char);

用typedef 把返回的函数类型定义一下会符合更阅读习惯一点
typedef void (*ReturnFun)(int*, int, char);
ReturnFun foo(int);

上篇XGUI的文章里,为了写自动推导模板参数的函数,我写了个很BT的模板函数,由于单独的typedef不能用模板参数,也就是这样的代码是不可能的:
template<typename ArgType>
typedef void (XCmdTarget::*CmdTargetMemFun)(const ArgType&);

但我的返回类型就是这个,为了符合返回函数指针函数的格式,用宏也不行,那只是字符替换,所以我只能硬来了。这样写仅仅为了调用时模板参数是自动推导,目的就是把子类的函数指针转化为基类的函数指针。
会看得很费劲…

template<typename DeriveCmdTargetType, typename EventArgType>
  inline
  void (XCmdTarget::*MakeMsg
  (void (DeriveCmdTargetType::*originMemFun)(const EventArgType&)))
  (const EventArgType&)
{
  typedef void (XCmdTarget::* DestFuncType)(const EventArgType&);
  return static_cast<DestFuncType>(originMemFun);
}


看明白了没?函数名叫MakeMsg,然后参数类型是void(DeriveCmdTargetType::*)(constEventArgType&)的一个成员函数指针类型,参数名是originMemFun,然后MakeMsg函数返回一个成员函数指针,类型为void (XCmdTarget::*)(constEventArgType&); 这下应该稍微清楚了点吧。
这样使用的时候就不用传任何模板参数了:

XButton* btn1 = new XButton(IDC_BUTTON1, 300, 200, 100, 50, "button1");
btn1->EventClick() = XEventHandler(&g_dialog, MakeMsg(&TestDialog::OnBtn1Click));
btn1->EventHover() = XMouseEventHandler(&g_dialog, MakeMsg(&TestDialog::OnBtnHover));
btn1->EventLeave() = XEventHandler(&g_dialog, MakeMsg(&TestDialog::OnBtnLeave));

恩,我也反对自己这样写代码,不过最终的目的还是达到了,就当练习一下边缘的C++语法。而且如果有人问道怎么写返回函数指针的函数定义,至少也知道如何写了。

原创粉丝点击