关于c/c++ 中的函数指针

本文探讨了C语言中如何利用函数指针实现回调机制,并提供了具体示例,同时对比了C++中实现类似功能的复杂性和解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c 使用函数指针与 c++ 虚拟函数不同,尽管 virtual function 的本质也是函数指针。在用 c 设计时,尽管没有抽象设计,但通过使用函数指针留出 call back 接口,就可以把不同的动作从代码中剥离出去,从而使得代码更加通用。一个例子,如果某个查找程序中需要一个排序, 而有不同的排序算法以适应不同的场合。为了保证查找程序的通用性,必须假设程序对外部环境一无所知,这时可以使用函数指针 call back.

typedef  void  (* SortFunctionPtr)(int* data, int size);

bool Search(int key,  int* data, int size, SortFunctionPtr sortFunction) {   

   ... 

   if (sortFunction != NULL) 

             (*sortFunction)(data, size);

   ...

}

另一个例子是 dll 中回调:

typedef void  (*CALLBACK)(short, short*, short);

typedef void  (__stdcall * FUNCTIONBINDING)(CALLBACK);

 

class CEventLog 

{

                HINSTANCE__*        m_hXXXX;

                FARPROC                m_pBindingRead;

                FARPROC                m_pBindingWrite;

                static bool Write(short type, short * buffer, short count);

                static bool Read(short type, short * buffer, short count);

               

}

 

CEventLog::CEventLog()

{

                m_hXXXX = ::LoadLibrary("xxxxx.dll");

                m_bLoadSuccess = m_hXXXX != NULL;

                if (!m_bLoadSuccess) {

                                ::MessageBox(NULL, "Error: Fail to load xxxxx.dll.", "Error", MB_ICONSTOP | MB_OK);

                                return;

                }

                m_pBindingRead = ::GetProcAddress(m_hXXXX,  "BindingReadFunction");

                m_pBindingWrite = ::GetProcAddress(m_ hXXXX, "BindingWriteFunction");

 

 

                (* (FUNCTIONBINDING) m_pBindingRead)((CALLBACK)  Read);

                (* (FUNCTIONBINDING) m_pBindingWrite)((CALLBACK)  Write);

 

这样,local Read, Write 函数被传递到 dll 中,让dll 可以调用 local 的不同 Read/Write 函数。

 

在 c++ 使用回调比较繁琐,因为成员函数被暗藏了一个 this 指针,用函数指针模板是一个常用的方法 ,不过必须指定类型,无法真正通用。另一个解决方法是把 this 指针传递给一个成员 static function,可以实现,不过代码看上去怪异。

....

typedef void (*PTR_CALLBACK)(void* sender, DWORD para);

class CDelegate

{

                PTR_CALLBACK                     m_pCallBack;

                void*                                   m_pInstance;

public:

               void SetEventHandler(void* pInstance, PTR_CALLBACK pCallBack)

                {

                                m_pInstance = (CDelegate*) pInstance;

                                m_pCallBack = pCallBack;

                }

 

                void Invoke(void* sender, DWORD para)

                {

                         if (m_pInstance != NULL && m_pCallBack != NULL)

                                   (*m_pCallBack)(sender, para);

                }

       ....

}

使用时:

class CMyClass

{

 ...

public:

   CMyClass(CDelegate* delegate) { delegate->SetEventHandler(this, MyClass::OnEvent); }

   voidDoSomething(); 

    .....

    static void OnEvent(void* sender, DWORD para);

}

void CMyClass::OnEvent(void* sender, DWORD para)

{

      CMyClass* me = (CMyClass*) sender;

      me->DoSomething(); 

}

 

这里有一个在 C++ 中不使用 static 函数实现的完整的callback

#if !defined(_Class_Delegate_)

#define _Class_Delegate_

 

/*************************************************************************************************

                Warning: Unsafe Code !!!

*************************************************************************************************/

 

#define SetEventHandler(instance, function) _SetEventHandler((instance), reinterpret_cast<PTR_CALLBACK>(function))

 

class CDelegate;

typedef void (CDelegate::*PTR_CALLBACK)(void* sender, DWORD para);

 

class CDelegate

{

                PTR_CALLBACK                     m_pCallBack;

                CDelegate*                                                m_pInstance;

 

public:

                CDelegate()

                {

                                m_pCallBack = NULL;

                                m_pInstance = NULL;

                }

 

                void _SetEventHandler(void* pInstance, PTR_CALLBACK pCallBack)

                {

                                m_pInstance = (CDelegate*) pInstance;

                                m_pCallBack = pCallBack;

                }

 

                void Invoke(void* sender, DWORD para)

                {

                                if (m_pInstance != NULL && m_pCallBack != NULL)

                                                (m_pInstance->*m_pCallBack)(sender, para);

                }

 

                void Cancel()

                {

                                m_pInstance = NULL;

                }

 

};

 

#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值