全能开发工程师:向前引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/n/144133.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
KOSWKOSW
上一篇 2024-10-24 15:27
下一篇 2024-10-24 15:27

相关推荐

发表回复

登录后才能评论