[轉]回調函數中調用類中的非靜態成員變量或非靜態成員函數


回調函數中調用類中的非靜態成員變量或非靜態成員函數

【問題】如何在類中封裝回調函數?
a.回調函數只能是全局的或是靜態的;
b.全局函數會破壞類的封裝性,故不予采用;
c.靜態函數只能訪問類的靜態成員,不能訪問類中非靜態成員。
 
1. 如何讓靜態函數訪問類的非靜態成員。
  a.聲明一靜態函數a(),將類實例對象指針做為參數傳入。如:

class A()
 {
  static void a(A *);     //靜態函數
  void b();         //非靜態函數 
}
void A::a(A * pThis)
{
  pThis->b();        //靜態函數中調用非靜態函數 
}

     b.回調函數中訪問非靜態成員
  由於回調函數往往有固定定義,並不接受  A * pThis 參數
  如:CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);

  
【解決方案1】:本方案當遇到有多個類實例對象時會有問題。原因是pThis指針只能指向一個對象。

class A()
{
      static void a();     //靜態回調函數
      void b();             //非靜態函數 
      static A * pThis;   //靜態對象指針
  }  

// 構造函數中將this指針賦給pThis,使得回調函數能通過pThis指針訪問本對象
A * A::pThis=NULL;
A::A()
{
      pThis = this;
}
void A::a()
{
      if ( pThis == NULL )
            return;
      pThis->b();     //回調函數中調用非靜態函數 
}

  【解決方案2】:本方案解決多個類實例對象時方案1的問題。用映射表存所有對象地址,每個對象保存自己的ID號。

typedef CMap<UINT, UINT, A*, A*> CAMap;
class A()
{
      static void a();      //靜態回調函數
      void b();              //非靜態函數 
      int m_ID;             //本對象在列表中的ID號
      static int m_SID;   //靜態當前對象ID.(需要時,將m_ID賦值給m_SID以起到調用本對象函數的功能)
      static CAMap m_Map; //靜態對象映射表
}
  
CAMap A::m_Map;
int   A::m_SID=0;

// 構造函數中將this指針賦給pThis,使得回調函數能通過pThis指針訪問本對象
A::A()
{
      if(m_Map.IsEmpty())
      {
            m_ID=1;
      }
      else
      { 
            m_ID=m_Map.GetCount()+1;
      }
      m_Map.SetAt( m_ID, this );
}

void A::a()
{
      if (m_Map.IsEmpty())
            return;
      A * pThis=NULL;
      if( m_Map.Lookup(m_SID,pThis) )
      {
            pThis->b();      // 回調函數中調用非靜態函數 
      };
}

 

【參考資料 感謝作者】
1、回調函數中調用類中的非靜態成員變量或非靜態成員函數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM