2KB项目,专业的源码交易网站 帮助 收藏 每日签到

C++11 中委派 (Delegates) 的实现

  • 时间:2019-01-23 18:50 编辑:2KB 来源:2KB.COM 阅读:392
  • 扫一扫,手机访问
  • 分享
摘要:
C/C++ 英文原文:Implementation of Delegates in C++11

介绍

在 C++ 中通过一个全局函数来绑定到对象的成员函数是很有用的,这个特性也存在于其他语言中,例如 C#的委派。在 C++ 中相当于成员函数指针,但是 并没有提供相应的特性。在这篇文章中,我想提出一个简单的 C++ 委派的实现,是用 C++ 成员函数指针和 C++11 的可变模板(variadic templates),目前这套实现方法仅支持 GNU C++ 4.7.0,在 Windows 下可使用 MinGW。

背景

在我的方法中奖提供一个create_delegate函数,可通过下面两种方法来调用:

  • create_delegate(&object, &member_function)
  • create_delegate(&function)

第一种方法创建一个对象并提供一个operator()成员函数,第二个方法生成一个函数指针,两种方法都兼容 type function<...>.

示例程序

首先我们定义一个包含多个方法的类:

class A
{
    int i;
public:    
    A(int k):i(k) {}

    auto get()const ->int { return i;}    
    auto set(int v)->void { i = v;}

    auto inc(int g)->int& { i+=g; return i;}
    auto incp(int& g)->int& { g+=i; return g;}

    auto f5 (int a1, int a2, int a3, int a4, int a5)const ->int
    {
        return i+a1+a2+a3+a4+a5;
    }

    auto set_sum4(int &k, int a1, int a2, int a3, int a4)->void
    {
        i+=a1+a2+a3+a4;
        k = i;
    }

    auto f8 (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const ->int
    {
        return i+a1+a2+a3+a4+a5+a6+a7+a8;
    }    

    static auto sqr(double x)->double { return x*x; }
};

请注意你并不需要一定使用 C++ 的 auto 函数语法,你也可以使用传统的方法,然后我们使用下面方法创建一个类:

A a(11);

接下来我们创建委派:

auto set1 = create_delegate(&a,&A::set);
auto inc = create_delegate(&a,&A::inc);
std::function<int(int&)> incp = create_delegate(&a,&A::incp);
auto af5  = create_delegate(&a,&A::f5);
auto set_sum4= create_delegate(&a,&A::set_sum4);
auto af8  = create_delegate(&a,&A::f8);
auto sqr = create_delegate(&A::sqr); // static function </int(int&)>

set1(25);
int x = 5;
int k = inc(x);
k = incp(x);
std::cout << "a.get():" << a.get() << std::endl;
std::cout << "k: " << k << std::endl;
std::cout << "x: " << x << std::endl;
std::cout << "af5(1,2,3,4,5): " << af5(1,2,3,4,5) << std::endl;

set_sum4(x,1,2,3,20);
std::cout << "after set_sum4(x,1,2,3,20)" << std::endl;
std::cout << "a.get(): " << a.get() << std::endl;
std::cout << "x: " << x << std::endl;
std::cout << "af8(1,2,3,4,5,6,7,8): " << af8(1,2,3,4,5,6,7,8) << std::endl;
std::cout << "sqr(2.1): " << sqr(2.1) << std::endl;


执行上述程序的打印结果如下:

a.get():30
k: 35
x: 35
af5(1,2,3,4,5): 45
after set_sum4(x,1,2,3,20)
a.get(): 56
x: 56
af8(1,2,3,4,5,6,7,8): 92
sqr(2.1): 4.41



关键点

对于一个不是 volatile 和 const 的简单函数而言,实现是非常简单的,我们只需要创建一个类保存两个指针,一个是对象,另外一个是成员函数:
template <class T, class R, class ... P>
struct  _mem_delegate
{
    T* m_t;
    R  (T::*m_f)(P ...);
    _mem_delegate(T* t, R  (T::*f)(P ...) ):m_t(t),m_f(f) {}
    R operator()(P ... p) 
    {
            return (m_t->*m_f)(p ...);
    }
};  


可变模板 variadic template 允许定义任意个数和类型参数的operator()函数,而create_function 实现只需简单返回该类的对象:

template <class T, class R, class ... P>
_mem_delegate<T,R,P ...> create_delegate(T* t, R (T::*f)(P ...))
{
    _mem_delegate<T,R,P ...> d(t,f);
    return d;
}



实际中,我们需要另外的三个实现用于覆盖 const、volatile 和 const volatile 三种成员函数,这也是为什么传统使用 #define 宏很便捷的原因,让你无需重写代码段,下面是完整的实现:

template <class F>
F* create_delegate(F* f)
{
    return f;
}
#define _MEM_DELEGATES(_Q,_NAME)
template <class T, class R, class ... P>
struct _mem_delegate ## _NAME
{
    T* m_t;
    R  (T::*m_f)(P ...) _Q;
    _mem_delegate ## _NAME(T* t, R  (T::*f)(P ...) _Q):m_t(t),m_f(f) {}
    R operator()(P ... p) _Q
    {
        return (m_t->*m_f)(p ...);
    }
};

template <class T, class R, class ... P>
    _mem_delegate ## _NAME<T,R,P ...> create_delegate(T* t, R (T::*f)(P ...) _Q)
{
    _mem_delegate ##_NAME<T,R,P ...> d(t,f);
    return d;
}

_MEM_DELEGATES(,Z)
_MEM_DELEGATES(const,X)
_MEM_DELEGATES(volatile,Y)
_MEM_DELEGATES(const volatile,W)



参考资料

  1. http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
  2. http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates
  3. [3] http://www.codeproject.com/Articles/13287/Fast-C-Delegate
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部