免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: buaaspy
打印 上一主题 下一主题

[C++] C++ 如何反射调用方法 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2013-12-11 18:10 |只看该作者
回复 9# windoze

好主意!
   

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
12 [报告]
发表于 2013-12-11 19:43 |只看该作者
buaaspy 发表于 2013-12-11 11:22
回复 2# truekbcl

确实如此,

想做到其他语言那样的反射,只可能在编译器做手脚,否则只能做到局部反射。最简单的大致如下:
1、定义一个method类,放置所有需要调用的函数类型
class method
{
    string _method_name;
    method * _next;
    const string & method_name() { return _method_name(); }
    virtual void invoke();
    virtual void invoke(int );
};
这表明,反射需要用到 obj->xxx(), obj->xxx(int)这两个类型的函数。


2、然后定义Class,
class Class
{
    method*>   _methods;
    method * get_method(const string & methodName);
};

3、在类中使用:
class A
{
    void test0(){ cout << "test"<<endl; }
    void test1(int x) { cout << "text " << x << endl; }
   
    // 以下2段代码,用宏生成,并且把method
    class method_A_test_0 : public method
   {
        method_A_test_0(const string & func):_method_name(func){}
        virtual void invoke() {test0(); }
   };

  class method_A_test_1 : public method
   {
        method_A_test_1(const string & func):_method_name(func){}
        virtual void invoke(int x) {test1(x); }
   };
};

4、
把A类中的method派生类放入到一个Class中,用静态变量Class即可。
比如在定义派生类时,生成链表,并放入到Class静态变量。

5、定义类工厂
class ClassFactory
{
   void register(const string & className);
   Class * get(const string & cn);
};


6、使用:
Class * p = ClassFactory.get("A");
p->get_method("test0").invoke();
p->get_method("test1").invoke(2);


改进:可以用模板与循环宏生成更多类型的参数,但是参数仍然只能是原始类型。但是也麻烦很多,我觉得意义不大。
另外,把method这个基类用宏来定义,如果在不同地方使用,修改也简单,其他代码都不变。
不建议使用反射,显然要慢很多。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
13 [报告]
发表于 2013-12-12 01:04 |只看该作者
本帖最后由 lost_templar 于 2013-12-12 01:10 编辑

组合使用 sfinae 与 enable_if,我实现了一个简单的,纯人肉的……

  1. #include <type_traits>
  2. #include <iostream>

  3. #define DETECT_METHOD(method)                                                   \
  4.     template<typename T, typename Sign>                                         \
  5.     struct class_has_method_##method                                         \
  6.     {                                                                           \
  7.         template <typename U, U> struct type_check;                             \
  8.         template <typename V> static char &chk(type_check<Sign, &V::method> *); \
  9.         template <typename   > static long  &chk(...);                          \
  10.         static bool const value = sizeof(chk<T>(0)) == sizeof(char);            \
  11.     }

  12. struct Test
  13. {
  14.     void display()
  15.     {
  16.         std::cout << "Test::display() called.\n";
  17.     }
  18. };

  19. struct Api
  20. {
  21.     void do_post()
  22.     {
  23.         std::cout << "Api::do_post() called.\n";
  24.     }
  25.     void do_get()
  26.     {
  27.         std::cout << "Api::do_get() called.\n";
  28.     }
  29. };

  30. DETECT_METHOD( display );

  31. template<typename T>
  32. typename std::enable_if<class_has_method_display<T, void( T::* )()>::value>::type display( T* pt )
  33. {
  34.     ( *pt ).display();
  35. }

  36. template<typename T>
  37. typename std::enable_if < !class_has_method_display<T, void( T::* )()>::value >::type display( T* pt )
  38. {
  39.     std::cerr << "No Method display defined for this struct.\n";
  40. }

  41. DETECT_METHOD( do_get );

  42. template<typename T>
  43. typename std::enable_if<class_has_method_do_get<T, void( T::* )()>::value>::type do_get( T* pt )
  44. {
  45.     ( *pt ).do_get();
  46. }

  47. template<typename T>
  48. typename std::enable_if < !class_has_method_do_get<T, void( T::* )()>::value >::type do_get( T* pt )
  49. {
  50.     std::cerr << "No Method do_get defined for this struct.\n";
  51. }

  52. DETECT_METHOD( do_post );

  53. template<typename T>
  54. typename std::enable_if<class_has_method_do_post<T, void( T::* )()>::value>::type do_post( T* pt )
  55. {
  56.     ( *pt ).do_post();
  57. }

  58. template<typename T>
  59. typename std::enable_if < !class_has_method_do_post<T, void( T::* )()>::value >::type do_post( T* pt )
  60. {
  61.     std::cerr << "No Method do_post defined for this struct.\n";
  62. }

  63. int main()
  64. {
  65.     /*
  66.     Test* test = (Test*)ClassFactory::create_instance_for_name("Test");
  67.     test->display();

  68.     Api* api = (Api*)ClassFactory::create_instance_for_name("Api");
  69.     api->do_post();
  70.     api->do_get();
  71.     */
  72.     Test* test = new Test {};
  73.     display( test );
  74.     do_post( test );
  75.     do_get( test );
  76.     delete test;
  77.     Api* api = new Api {};
  78.     display( api );
  79.     do_post( api );
  80.     do_get( api );
  81.     delete api;
  82.     return 0;
  83. }


复制代码
输出是:
  1. Test::display() called.
  2. No Method do_post defined for this struct.
  3. No Method do_get defined for this struct.
  4. No Method display defined for this struct.
  5. Api::do_post() called.
  6. Api::do_get() called.
复制代码
只是不知是否合乎楼主需求。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP