一、Forwarders的基礎概念
在C++中,為了避免代碼重複,我們會使用函數指針、虛函數等來實現代碼的復用。然而,對於一些比較複雜的應用,這種方式仍然相對繁瑣且易錯。而在這種情況下,Forwarders就可以起到強有力的作用:它可以在一些對象之間建立聯繫,從而將對象與該對象下面的所有函數之間相連。
我們使用Forwarders的主要目的,在於實現除去接口的抽象化代碼。舉個例子,如果之前我們的強制類型轉換與函數名的供養方式存在衝突,則我們可以採用以下的解決方案:
class MyClass { public: int doSomething(double x) { cout << "in MyClass::doSomething(" << x << ")
"; return(int)x; } }; class YourClass { public: int doit() { typedef int (MyClass::*pmf_type)(double); pmf_type pmf = &MyClass::doSomething; MyClass mc; int result = (mc.*pmf)(3.14); cout << "result = " << result << endl; return result; } };
而現在,我們只需要使用一個typename參數即可實現。
template class Forwarder { public: Forwarder(R (T::*pmf)(Args...)) : pmf(pmf) {} R Call(T* Object, Args... args) { return (Object->*pmf)(args...); } private: R (T::*pmf)(Args...); }; struct MyClass { int DoSomething(double x) { return(x); } }; struct YourClass { Forwarder f2{&MyClass::DoSomething}; int callDoSomething(MyClass* p, double x) { return f2.Call(p,x); } };
值得注意的是,對於嵌套類定義(如MyClass::*)來說,我們需要在參數表中進行一個小小的變形,即使用typedef進行訪問,而非直接訪問。
二、Forwarders的操作與實現
除了以上簡單的應用外,Forwarders還可以擁有更加廣泛的應用場景。比如說,在某個函數的傳遞過程中,如果該函數擁有過多參數,則可以令其使用Forwarders處理參數。
在此時,我們需要令該指針指向一個Forwarder類對象。這個操作看起來比較困難,但實際上代碼的實現非常簡單,如下所示:
template class Function { public: typedef std::function HandlerType; void operator+=( HandlerType h ) { handlers.push_back( h ); } void operator()( Args... args ) const { for( auto& handler : handlers ) handler( args... ); } private: std::vector handlers; }; template class Forwarder { public: Forwarder(R (T::*pmf)(Args...)) : pmf(pmf) {} R Call(T* Object, Args... args) { return (Object->*pmf)(args...); } operator typename Function::HandlerType() { return [&](Args... args) { Call(object, args...); }; } private: T* object; R (T::*pmf)(Args...); };
在這段代碼中,我們首先定義了一個Function類,它能夠編寫抽象化函數,並在不同的對象之間建立聯繫。而在Forwarder的實現中,我們需要在裡面編寫一個左移運算符,將該對象的類型轉化為Function類的HandlerType類型即可。
三、Forwarders的注意事項與用途分析
在編寫回調函數或者說Adapters函數過程中,我們需要對Forwarders進行左移運算符的操作,而同樣需要一定的規範來進行操作。
正如上文所述,我們可以使用Function類和Forwarder類將兩個不同的類之間聯繫起來,實現類的接口化。同時,我們還需要注意構造函數中的typename之間的順序。
但需要注意的是,雖然Forwarders具有很強的抽象化原則,不過我們在進行實際操作時,還需要考慮它的數據類型轉換問題。因為Forwarders會在代碼實現中進行許多樣式和指針類型的轉化,如果不加入安全校驗的話,該方案存在許多隱患。
四、Forwarders的優缺點分析
Forwarders在代碼的復用以及模板代碼的高效展示方面,都具有一定的優勢。然而,由於其調用過程較為繁瑣,不太容易被用戶接受。同時,在數據類型安全方面,它還存在一些潛在的問題。
總體來說,在解決抽象化代碼問題以及模板的展示方面,Forwarders具有不可忽視的作用。只不過,對於安全性和程序效率等問題,我們需要在使用的時候進行一定的權衡和考慮。
原創文章,作者:KOSW,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/144133.html