首页 > 编程 > C++ > 正文

C++中关于委派(Delegates)的实现示例

2020-05-23 14:18:16
字体:大 中 小
来源:转载
供稿:网友

这篇文章主要介绍了C++中关于委派(Delegates)的实现示例,针对C++11的一些新特性进行讲解,需要的朋友可以参考下

介绍

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

背景

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

 

 
  1. create_delegate(&object, &member_function) 
  2. 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 函数语法,你也可以使用传统的方法,然后我们使用下面方法创建一个类:

 

 
  1. A 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&)> 
  8.  
  9.  
  10. set1(25); 
  11. int x = 5; 
  12. int k = inc(x); 
  13. k = incp(x); 
  14. std::cout << "a.get():" << a.get() << std::endl; 
  15. std::cout << "k: " << k << std::endl; 
  16. std::cout << "x: " << x << std::endl; 
  17. std::cout << "af5(1,2,3,4,5): " << af5(1,2,3,4,5) << std::endl; 
  18.  
  19. set_sum4(x,1,2,3,20); 
  20. std::cout << "after set_sum4(x,1,2,3,20)" << std::endl; 
  21. std::cout << "a.get(): " << a.get() << std::endl; 
  22. std::cout << "x: " << x << std::endl; 
  23. std::cout << "af8(1,2,3,4,5,6,7,8): " << af8(1,2,3,4,5,6,7,8) << std::endl; 
  24. 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) 

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表