[問題] 將 class B 之 mem. func 塞到 class A 之 func.ptr

看板C_and_CPP (C/C++)作者 (卡卡獸)時間10年前 (2015/07/17 19:13), 10年前編輯推噓5(5022)
留言27則, 5人參與, 最新討論串1/3 (看更多)
開發平台(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

07/17 19:26, , 1F
UpdateDisplay改成global fun,或讓Display建構式能吃
07/17 19:26, 1F

07/17 19:27, , 2F
PlaneDlg的mem func
07/17 19:27, 2F

07/17 19:28, , 3F
改 Global Func 知道怎做 , 但 Display 怎改 ctor 才能讓
07/17 19:28, 3F

07/17 19:29, , 4F
PlaneDlg 的 mem func 吃進來 ?
07/17 19:29, 4F

07/17 19:46, , 5F
typedef void (PlaneDlg::*cb_t)(int);
07/17 19:46, 5F

07/17 19:46, , 6F
cb_t m_CallBackFunc;
07/17 19:46, 6F

07/17 19:47, , 7F
Display(cb_t cb = NULL) : m_CallBackFunc(cb){}
07/17 19:47, 7F

07/17 19:49, , 8F
要呼叫m_CallBackFunc時要給物件的instance,所以
07/17 19:49, 8F

07/17 19:49, , 9F
ToUpdateDisplay那邊也會compile error
07/17 19:49, 9F

07/17 19:50, , 10F
而且基本上這段代碼有物件循環參考的問題 我不太確定
07/17 19:50, 10F

07/17 19:51, , 11F
你真正的使用方式為何 感覺應該可以用cb_fun+cb_data
07/17 19:51, 11F

07/17 19:51, , 12F
的慣用法寫得更乾淨才對
07/17 19:51, 12F
我簡略比喻一下我的情況 (這例子應該蠻貼切的) 。 現在程式裡假設有 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

07/17 21:38, , 13F
建議context(天氣資料)明確區分出來 自成一個物件
07/17 21:38, 13F

07/17 21:39, , 14F
感覺沒有必要特地使用mem func ptr來作callback
07/17 21:39, 14F

07/17 21:40, , 15F
model(天氣資料)-view(Display)-controller
07/17 21:40, 15F

07/17 22:33, , 16F
不考慮多型? http://ideone.com/pEwTYa
07/17 22:33, 16F

07/17 22:41, , 17F
07/17 22:41, 17F

07/17 22:41, , 18F
或是std::function + std::bind
07/17 22:41, 18F

07/17 22:56, , 19F
感謝 kevinggwn 與 azureblaze , 你們提供的方案都可解決
07/17 22:56, 19F

07/17 22:56, , 20F
我的問題 , 謝謝
07/17 22:56, 20F

07/18 09:15, , 21F
boost::function 也可以試試
07/18 09:15, 21F

07/18 12:31, , 22F
@shadow0326 , 您說的物件循環相依問題我今天遇到了 ,
07/18 12:31, 22F

07/18 12:31, , 23F
用其他版友的方法可以避掉 , 謝謝.
07/18 12:31, 23F

07/18 12:32, , 24F
@LiloHuang,boost 比較尷尬,要安裝額外 lib 需要同意 @@
07/18 12:32, 24F

07/19 17:45, , 25F
boost 裡頭的好東西可不少 XD license 也相當適合商用
07/19 17:45, 25F

07/19 17:46, , 26F
像是 Boost.Preprocessor 或是 Boost.MPL 都相當好用
07/19 17:46, 26F

07/19 17:49, , 27F
有興趣也可以看看介紹 https://goo.gl/X02gUp 誠心推薦
07/19 17:49, 27F
文章代碼(AID): #1LgED631 (C_and_CPP)
文章代碼(AID): #1LgED631 (C_and_CPP)