看板 C_and_CPP 關於我們 聯絡資訊
開發平台(Platform): (Ex: VC++, GCC, Linux, ...) vs2010 問題(Question): 我想在自己的 class Display 實現 callback 功能 , 讓其他 class 使用 目前我想比較正式的方法應該是用 template 方式去做,但這份 class 要改成 template 的話有些工程,故想加上 function pointer 方式去做, 但發現好像不能塞其他 class 之 member function, 問題之程式碼簡化如下, 同步附 Code http://codepad.org/nT3XDA5q ////// class Display { private: void (*m_CallBackFunc)(int) ; public: Display( void (*CallBackFunc)(int) = NULL) : m_CallBackFunc( CallBackFunc ) { } void ToUpdateDisplay(int iSel) { if(m_CallBackFunc) if(rand() & 1) // some condition here m_CallBackFunc(iSel); } }; /////// class PlaneDlg { private: Display m_display; public: PlaneDlg () : m_display ( UpdateDisplay ) // <- 人是它殺的 ... // : m_dysplay ( & PlaneDlg :: UpdateDisplay) // 這樣還是救不了它 .. { } void UpdateDisplay(int iGrp) { // do something.. } }; 上述黃色部份我不知道該怎麼才能讓它過 , vs 的錯誤訊息是 'Display::Display(,void (__cdecl *)(int))' : 無法將參數 2 從 'void (__thiscall PlaneDlg::* )(int)' 轉換成 'void (__cdecl *)(int)' 希望能動到最小的 Display ,去實現這個功能。 另也希望版友能針對此問題提供一些架構上的意見, 避開日後同樣的問題再重現。 非常感謝各位! -- 「自從我學了 C# , 人都變聰明 , 考試都考一百分」 「自從我學了 VB , 皮膚都變好 , 人也變漂亮了 」 「自從我學了 Java , 明顯變壯 , 個子也變高了 」 「自從我學了 C++ , 內分泌失調 , 頭都禿了... 」 < Kuso 星爺語錄 > -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 60.251.92.138 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1437131590.A.0C1.html ※ 編輯: EdisonX (60.251.92.138), 07/17/2015 19:14:41
shadow0326: UpdateDisplay改成global fun,或讓Display建構式能吃 07/17 19:26
shadow0326: PlaneDlg的mem func 07/17 19:27
EdisonX: 改 Global Func 知道怎做 , 但 Display 怎改 ctor 才能讓 07/17 19:28
EdisonX: PlaneDlg 的 mem func 吃進來 ? 07/17 19:29
shadow0326: typedef void (PlaneDlg::*cb_t)(int); 07/17 19:46
shadow0326: cb_t m_CallBackFunc; 07/17 19:46
shadow0326: Display(cb_t cb = NULL) : m_CallBackFunc(cb){} 07/17 19:47
shadow0326: 要呼叫m_CallBackFunc時要給物件的instance,所以 07/17 19:49
shadow0326: ToUpdateDisplay那邊也會compile error 07/17 19:49
shadow0326: 而且基本上這段代碼有物件循環參考的問題 我不太確定 07/17 19:50
shadow0326: 你真正的使用方式為何 感覺應該可以用cb_fun+cb_data 07/17 19:51
shadow0326: 的慣用法寫得更乾淨才對 07/17 19:51
我簡略比喻一下我的情況 (這例子應該蠻貼切的) 。 現在程式裡假設有 6 個地方的天氣預報, 我的 Display 其實就是讓 user 去 點選 "要看哪個地方" 的天氣, 而 PlaneDlg 就是 每個地方天氣 的 detail 顯示 ( 像是溫度,溼度,降雨率等 ), 換句話說,那個 "點選" 就是 Display 要去觸發 callback func 的時間, 但除了 天氣預報 ,這個 Display 還可以要用來看每個地方的 地方新聞、奇人異事、阿貓阿狗、今日最美、今日最宅 ... etc class 我想這應該除了在 每個 class 被動的呼叫 Display 的成員, 還有更好的方法可以達成目標 ? 所以想到 function pointer 做 call back. 但照上面 shadow 的 typedef func ptr 看來, 是否我的 Display 要提供給幾個 class 使用, 裡面就要塞幾個 function pointer ? (因為 type 不同 ) 請問是這樣嗎? 以上,希望我的說明能對問題與需求提供更多線索,謝謝各位的不吝指教, 也謝謝 shadow 的意見。 推 stupid0319: 自從我學了 C++ , 內分泌失調 , 頭都禿了... 07/17 19:54 ^^^ 人生還是很美好的 Orz ※ 編輯: EdisonX (123.195.169.158), 07/17/2015 20:35:21 ※ 編輯: EdisonX (123.195.169.158), 07/17/2015 20:40:23
shadow0326: 建議context(天氣資料)明確區分出來 自成一個物件 07/17 21:38
shadow0326: 感覺沒有必要特地使用mem func ptr來作callback 07/17 21:39
shadow0326: model(天氣資料)-view(Display)-controller 07/17 21:40
kevingwn: 不考慮多型? http://ideone.com/pEwTYa 07/17 22:33
azureblaze: http://ideone.com/pE8z2L 07/17 22:41
azureblaze: 或是std::function + std::bind 07/17 22:41
EdisonX: 感謝 kevinggwn 與 azureblaze , 你們提供的方案都可解決 07/17 22:56
EdisonX: 我的問題 , 謝謝 07/17 22:56
LiloHuang: boost::function 也可以試試 07/18 09:15
EdisonX: @shadow0326 , 您說的物件循環相依問題我今天遇到了 , 07/18 12:31
EdisonX: 用其他版友的方法可以避掉 , 謝謝. 07/18 12:31
EdisonX: @LiloHuang,boost 比較尷尬,要安裝額外 lib 需要同意 @@ 07/18 12:32
LiloHuang: boost 裡頭的好東西可不少 XD license 也相當適合商用 07/19 17:45
LiloHuang: 像是 Boost.Preprocessor 或是 Boost.MPL 都相當好用 07/19 17:46
LiloHuang: 有興趣也可以看看介紹 https://goo.gl/X02gUp 誠心推薦 07/19 17:49