Stackoverflow中提出了這樣一個問題:假設咱們實現了一個User類,Library類,如今Library類中utility須要回調User中func方法,總結答案,常見的幾種方法以下:node
下面則是很是規方法。ios
基於tag dispatch的調用方法,利用空類實現標籤回調,在註冊方法時提供不一樣的空類模板參數實現不一樣的調用,代碼以下:函數
template<class T> struct tag_t { using type = T; constexpr tag_t() {} }; struct ForLibrary; template <class T> class Library { public: T *node = nullptr; Library(T *n):node(n) {} void utility() { func(tag_t<ForLibrary>(),node); }; }; class User { public: void func() { cout << "User::func" << endl; } friend void func(tag_t<ForLibrary>, User *self) { self->func(); } };
不得不說,這種方法太妙了,既能夠動態變化回調方法(只需修改ForLibrary參數)又無需改變User類實現,並且一切都是靜態調用無虛函數開銷。this
利用模板基類實現靜態多態機制,經過在基類中強轉類型調用子類方法,實現路由回調,代碼以下:spa
#include <iostream> #include <functional> template<typename T> class ICallback { public: void callback() { static_cast<T*>(this)->func(); } }; class User : public ICallback<User> { public: void func(){ std::cout << "User::func" << std::endl; } }; template<class T,class F=std::function<void(void)>> class Library { private: T *node; public: Library(T* n):node(n) { } void utility() { std::mem_fn(&T::callback)(*node); } void utility(F func) { func(); } }; int main() { User user; Library<User> lib(&user); lib.utility(); lib.utility(std::bind(&User::callback,user)); return 0; }
回調類與實現類相互解耦又能避免虛函數多態。指針