现在的位置: 首页 > 综合 > 正文

C++指针函数指针

2013年11月25日 ⁄ 综合 ⁄ 共 1205字 ⁄ 字号 评论关闭

   C++比C语言有更严格的静态类型,更加强调类型安全,强调编译时检查。因此,对于C语言中最容易错用的指针,更是不能放过:C++的指针被分成数据指针,数据成员指针,函数指针,成员函数指针,而且不能随便相互转换。而且这些指针的声明格式都不一样:


还有一个更重要的区别是,指针所占的空间也不一样了。即使在32位系统中,所占的空间也有可能是4字节、8字节、12字节甚至16字节,这个依据平台及编译器,有很大的变化。

尽管C++中仍然有万能指针void*,但它却属于被批斗的对象,而且再也不能“万能”了。它不能转换成成员指针。

这样一来,C++的指针就变得很尴尬:我们需要一种指针能够指向同一类型的数据,不管这个数据是普通数据,还是成员数据;我们更需要一种指针能够指向同一类型的函数,不管这个函数是静态函数,还是成员函数。但是没有,至少从现在的C++标准中,还没有看到。

自从有了类,我们开始按照 数据+操作 的方式来组织数据结构;自从有了模板,我们又开始把 数据 和 算法 分离,以便重用,实在够折腾人的。但不管怎么折腾,现在大多数函数都不再单身,都嫁给了类,进了围城。(^_^)可是我们仍然需要能够自由调用这些成员函数。

考虑一下windows下的定时调用。SetTimer函数的原型是这样的:

UINT_PTR
SetTimer(

    HWND hWnd,

    UINT_PTR nIDEvent,

    UINT uElapse,

    TIMERPROC lpTimerFunc

);

其中,参数就不解释了,这个函数估计大多数windows开发人员都知道。lpTimerFunc是个会被定时调用的函数指针。假如我们不通过WM_TIMER消息来触发定时器,而是通过lpTimerFunc来定时工作,那么我们就只能使用普通函数或静态函数,而无论如何都不能使用成员函数,哪怕通过静态函数转调也不行。

再考虑一下线程的创建:

uintptr_t
_beginthread(

   void( *start_address )( void * ),

   unsigned stack_size,

   void *arglist

);

start_address仍然只支持普通函数。不过这回好了,它允许回调函数一个void*参数,它将会arglist作为参数来调用start_address.于是,聪明的C++程序员,就利用arglist传递this指针,从而利用静态函数成功的调用到了成员函数了:

class
mythread

{

  public:

    static void doit(void* pThis)

    {

    ((mythread*)pThis)->doit();

    }

    void doit(...){}

};


main()

{

  ...

  mythread* pmt = new mythread;

  _beginthread(&mythread::doit, 0, (void*)pmt);


  ...

}

抱歉!评论已关闭.