一、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
微信掃一掃
支付寶掃一掃