全能開發工程師:向前引Forwarders的多方面使用

一、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-tw/n/144133.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
KOSW的頭像KOSW
上一篇 2024-10-24 15:27
下一篇 2024-10-24 15:27

相關推薦

發表回復

登錄後才能評論