一、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