嚴格來講, C 和 C++ 都不支持將函數作為參數,真正作為參數的,實際上是 pass-by-value 的函數指針, 作為函數指針的模擬, Functor 作為參數時候也是按值傳遞的,有些 STL 的實現中,將 Functor 作為引用傳遞甚至不能通過編譯。這也就要求我們將 Functor 設計得當,以滿足傳值:
- Functor 應該盡量小:
否則的話, Functor 的拷貝將會變得昂貴。 - Functor 應該為單態 (monomorphic): —— 不用使用虛函數
如果算法需要的是基類 Functor,但傳入的是子類的話,拷貝過程中可能會引起 切片問題 。
但,離開了多態與繼承的 C++ ,也就失去了后面的 ++, 變成了 C 。這里有一個辦法可以將龐大的多態 Functor 分解成符合需求的 Functor,即將數據以及多態的部分封裝成單獨的類,然后在 Functor 中存儲該類的指針,換句話說: Bridge Mode。
例如下面的這個 BPFC (Big Polymoriphic Functor Class):
template <typename T> class BPFC : public unary_functor<T, void>() { public: // XXX: This is virtual function, may cause slicing issue. virtual void operator()(const T& val) const; private: Widget w; int x; };
我們可以將其中的數據和多態部分拆分,形成下面的 Functor:
template <typename T> class BPFCImpl { public: virtual void operator(const T& val) const; virtual ~BPFCImpl(); private: Widget w; int x; }; template <typename T> class BPFC : public unary_functor<T,void> { public: void operator()(const T& val) const { pImpl->operator(val); // forward it to BPFCImpl } private: BPFCImpl<T>* pImpl; };
切記: Make functors small and monomorphic!
(轉載請注明出處,使用許可:署名-非商業性使用-相同方式共享 3.0 中國大陸許可協議 。)