开发者社区> 问答> 正文

C++11 中委派 (Delegates) 如何实现

a123456678 2016-03-03 17:24:42 912

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

C# C语言 C++ Windows
分享到
取消 提交回答
全部回答(1)
  • a123456678
    2019-07-17 18:51:43

    在我的方法中奖提供一个create_delegate函数,可通过下面两种方法来调用:
    create_delegate(&object, &member_function)
    create_delegate(&function)
    第一种方法创建一个对象并提供一个operator()成员函数,第二个方法生成一个函数指针,两种方法都兼容 type function<...>.

    1 class A
    2 {
    3    int i;
    4 public:   
    5    A(int k):i(k) {}
    6 
    7    auto get()const ->int { return i;}   
    8    auto set(int v)->void { i = v;}
    9 
    10    auto inc(int g)->int& { i+=g; return i;}
    11    auto incp(int& g)->int& { g+=i; return g;}
    12 
    13    auto f5 (int a1, int a2, int a3, int a4, int a5)const ->int
    14    {
    15        return i+a1+a2+a3+a4+a5;
    16    }
    17 
    18   auto set_sum4(int &k, int a1, int a2, int a3, int a4)->void
    19    {
    20        i+=a1+a2+a3+a4;
    21        k = i;
    22    }
    23 
    24    auto f8 (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const ->int
    25    {
    26        return i+a1+a2+a3+a4+a5+a6+a7+a8;
    27    }   
    28 
    29    static auto sqr(double x)->double { return x*x; }
    30 };

    请注意你并不需要一定使用 C++ 的 auto 函数语法,你也可以使用传统的方法,然后我们使用下面方法创建一个类:
    `
    1A a(11);
    `
    接下来我们创建委派:

    1 auto set1 = create_delegate(&a,&A::set);
    2 auto inc = create_delegate(&a,&A::inc);
    3 std::function<int(int&)> incp = create_delegate(&a,&A::incp);
    4 auto af5  = create_delegate(&a,&A::f5);
    5 auto set_sum4= create_delegate(&a,&A::set_sum4);
    6 auto af8  = create_delegate(&a,&A::f8);
    7 auto sqr = create_delegate(&A::sqr); // static function </int(int&)>
    1 set1(25);
    2 int x = 5;
    3 int k = inc(x);
    4 k = incp(x);
    5 std::cout << "a.get():" << a.get() << std::endl;
    6 std::cout << "k: " << k << std::endl;
    7 std::cout << "x: " << x << std::endl;
    8 std::cout << "af5(1,2,3,4,5): " << af5(1,2,3,4,5) << std::endl;
    9  
    10 set_sum4(x,1,2,3,20);
    11 std::cout << "after set_sum4(x,1,2,3,20)" << std::endl;
    12 std::cout << "a.get(): " << a.get() << std::endl;
    13 std::cout << "x: " << x << std::endl;
    14 std::cout << "af8(1,2,3,4,5,6,7,8): " << af8(1,2,3,4,5,6,7,8) << std::endl;
    15 std::cout << "sqr(2.1): " << sqr(2.1) << std::endl;

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

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

    关键点

    对于一个不是 volatile 和 const 的简单函数而言,实现是非常简单的,我们只需要创建一个类保存两个指针,一个是对象,另外一个是成员函数:

    1 template <class T, class R, class ... P>
    2 struct  _mem_delegate
    3 {
    4   T* m_t;
    5    R  (T::*m_f)(P ...);
    6    _mem_delegate(T* t, R  (T::*f)(P ...) ):m_t(t),m_f(f) {}
    7    R operator()(P ... p)
    8    {
    9            return (m_t->*m_f)(p ...);
    10    }
    11 };

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

    1 template <class T, class R, class ... P>
    2 _mem_delegate<T,R,P ...> create_delegate(T* t, R (T::*f)(P ...))
    3 {
    4    _mem_delegate<T,R,P ...> d(t,f);
    5    return d;
    6 }

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

    1 template <class F>
    2 F* create_delegate(F* f)
    3 {
    4    return f;
    5 }
    6 #define _MEM_DELEGATES(_Q,_NAME)\
    7 template <class T, class R, class ... P>\
    8 struct _mem_delegate ## _NAME\
    9 {\
    10   T* m_t;\
    11    R  (T::*m_f)(P ...) _Q;\
    12    _mem_delegate ## _NAME(T* t, R  (T::*f)(P ...) _Q):m_t(t),m_f(f) {}\
    13    R operator()(P ... p) _Q\
    14    {\
    15        return (m_t->*m_f)(p ...);\
    16    }\
    17 };\
    18 \
    19 template <class T, class R, class ... P>\
    20     _mem_delegate ## _NAME<T,R,P ...> create_delegate(T* t, R (T::*f)(P ...) _Q)\
    21 {\
    22    _mem_delegate ##_NAME<T,R,P ...> d(t,f);\
    23    return d;\
    24 }
    25  
    26 _MEM_DELEGATES(,Z)
    27 _MEM_DELEGATES(const,X)
    28 _MEM_DELEGATES(volatile,Y)
    29 _MEM_DELEGATES(const volatile,W)
    0 0

集结各类场景实战经验,助你开发运维畅行无忧

推荐文章
相似问题