久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

<tfoot id='ICdmG'></tfoot>
  • <legend id='ICdmG'><style id='ICdmG'><dir id='ICdmG'><q id='ICdmG'></q></dir></style></legend>
          <bdo id='ICdmG'></bdo><ul id='ICdmG'></ul>
        <i id='ICdmG'><tr id='ICdmG'><dt id='ICdmG'><q id='ICdmG'><span id='ICdmG'><b id='ICdmG'><form id='ICdmG'><ins id='ICdmG'></ins><ul id='ICdmG'></ul><sub id='ICdmG'></sub></form><legend id='ICdmG'></legend><bdo id='ICdmG'><pre id='ICdmG'><center id='ICdmG'></center></pre></bdo></b><th id='ICdmG'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='ICdmG'><tfoot id='ICdmG'></tfoot><dl id='ICdmG'><fieldset id='ICdmG'></fieldset></dl></div>

        <small id='ICdmG'></small><noframes id='ICdmG'>

        在 C++ 中動態創建和調用類方法的最簡單方法是什

        What is the simplest way to create and call dynamically a class method in C++?(在 C++ 中動態創建和調用類方法的最簡單方法是什么?)
          <bdo id='NTrkw'></bdo><ul id='NTrkw'></ul>

          • <i id='NTrkw'><tr id='NTrkw'><dt id='NTrkw'><q id='NTrkw'><span id='NTrkw'><b id='NTrkw'><form id='NTrkw'><ins id='NTrkw'></ins><ul id='NTrkw'></ul><sub id='NTrkw'></sub></form><legend id='NTrkw'></legend><bdo id='NTrkw'><pre id='NTrkw'><center id='NTrkw'></center></pre></bdo></b><th id='NTrkw'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='NTrkw'><tfoot id='NTrkw'></tfoot><dl id='NTrkw'><fieldset id='NTrkw'></fieldset></dl></div>
          • <small id='NTrkw'></small><noframes id='NTrkw'>

            • <tfoot id='NTrkw'></tfoot>

                <legend id='NTrkw'><style id='NTrkw'><dir id='NTrkw'><q id='NTrkw'></q></dir></style></legend>
                  <tbody id='NTrkw'></tbody>
                1. 本文介紹了在 C++ 中動態創建和調用類方法的最簡單方法是什么?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

                  問題描述

                  我想用類名和方法、唯一標識符和指向方法的指針填充映射.

                  I want to fill a map with class name and method, a unique identifier and a pointer to the method.

                  typedef std::map<std::string, std::string, std::string, int> actions_type;
                  typedef actions_type::iterator actions_iterator;
                  
                  actions_type actions;
                  actions.insert(make_pair(class_name, attribute_name, identifier, method_pointer));
                  
                  //after which I want call the appropriate method in the loop
                  
                  while (the_app_is_running)
                  {
                      std::string requested_class = get_requested_class();
                      std::string requested_method = get_requested_method();
                  
                      //determine class
                      for(actions_iterator ita = actions.begin(); ita != actions.end(); ++ita)
                      {
                          if (ita->first == requested_class && ita->second == requested_method)
                          {
                              //class and method match
                              //create a new class instance
                              //call method
                          }
                      }
                  }
                  

                  如果方法是靜態的,那么一個簡單的指針就足夠了,問題很簡單,但我想動態創建對象,所以我需要存儲一個指向類的指針和方法的偏移量,我不知道這是否有效(如果偏移量總是相同等).

                  If the method is static then a simple pointer is enough and the problem is simple, but I want to dynamically create the object so I need to store a pointer to class and an offset for the method and I don't know if this works (if the offset is always the same etc).

                  問題在于 C++ 缺乏反射,在解釋性語言中,有反射的等效代碼應該是這樣的(PHP 中的例子):

                  The problem is that C++ lacks reflection, the equivalent code in a interpreted language with reflection should look like this (example in PHP):

                  $actions = array
                  (
                       "first_identifier" => array("Class1","method1"),
                       "second_identifier" => array("Class2","method2"),
                       "third_identifier" => array("Class3","method3")
                  );
                  
                  while ($the_app_is_running)
                  {
                       $id = get_identifier();
                  
                       foreach($actions as $identifier => $action)
                       {
                           if ($id == $identifier)
                           {
                               $className = $action[0];
                               $methodName = $action[1];
                  
                               $object = new $className() ;
                  
                               $method = new ReflectionMethod($className , $methodName);
                               $method -> invoke($object);    
                           }
                       }
                   }
                  

                  PS:是的,我正在嘗試用 C++ 制作一個(網絡)MVC 前端控制器.我知道我知道為什么不使用 PHP、Ruby、Python(在此處插入您最喜歡的網絡語言)等?我只想要 C++.

                  PS: Yes I'm trying to make a (web) MVC front controller in C++. I know I know why don't use PHP, Ruby, Python (insert your favorite web language here) etc?, I just want C++.

                  推薦答案

                  我在上幾個小時寫了這些東西,并將它添加到我的有用東西集合中.最困難的是處理工廠函數,如果你想創建的類型沒有任何關系.為此,我使用了 boost::variant.你必須給它一組你想要使用的類型.然后它將跟蹤變體中當前的活動"類型是什么.(boost::variant 是所謂的歧視聯合).第二個問題是如何存儲函數指針.問題是指向A 成員的指針不能存儲到指向B 成員的指針.這些類型是不兼容的.為了解決這個問題,我將函數指針存儲在一個重載其 operator() 并采用 boost::variant:

                  I wrote that stuff last hours, and added it to my collection of useful stuff. The most difficult thing is to cope with the factory function, if the types you want to create are not related in any way. I used a boost::variant for this. You have to give it a set of types you ever want to use. Then it will keep track what is the current "active" type in the variant. (boost::variant is a so-called discriminated union). The second problem is how you store your function pointers. The problem is that a pointer to a member of A can't be stored to a pointer to a member of B. Those types are incompatible. To solve this, i store the function pointers in an object that overloads its operator() and takes a boost::variant:

                  return_type operator()(variant<possible types...>)
                  

                  當然,所有類型的函數都必須具有相同的返回類型.否則整個游戲就沒有什么意義了.現在代碼:

                  Of course, all your types' functions have to have the same return type. Otherwise the whole game would only make little sense. Now the code:

                  #include <boost/variant.hpp>
                  #include <boost/function.hpp>
                  #include <boost/bind.hpp>
                  #include <boost/tuple/tuple.hpp>
                  #include <boost/mpl/identity.hpp>
                  #include <boost/function_types/parameter_types.hpp>
                  #include <boost/function_types/result_type.hpp>
                  #include <boost/function_types/function_arity.hpp>
                  #include <boost/preprocessor/repetition.hpp>
                  #include <map>
                  #include <string>
                  #include <iostream>
                  
                  // three totally unrelated classes
                  // 
                  struct foo {
                      std::string one() {
                          return "I ";
                      }
                  };
                  
                  struct bar {
                      std::string two() {
                          return "am ";
                      }
                  };
                  
                  struct baz {
                      std::string three() const {
                          return "happy!";
                      }
                  };
                  
                  // The following are the parameters you have to set
                  //
                  
                  // return type
                  typedef std::string return_type;
                  // variant storing an object. It contains the list of possible types you
                  // can store.
                  typedef boost::variant< foo, bar, baz > variant_type;
                  // type used to call a function on the object currently active in
                  // the given variant
                  typedef boost::function<return_type (variant_type&)> variant_call_type;
                  
                  // returned variant will know what type is stored. C++ got no reflection, 
                  // so we have to have a function that returns the correct type based on
                  // compile time knowledge (here it's the template parameter)
                  template<typename Class>
                  variant_type factory() {
                      return Class();
                  }
                  
                  namespace detail {
                  namespace fn = boost::function_types;
                  namespace mpl = boost::mpl;
                  
                  // transforms T to a boost::bind
                  template<typename T>
                  struct build_caller {
                      // type of this pointer, pointer removed, possibly cv qualified. 
                      typedef typename mpl::at_c<
                          fn::parameter_types< T, mpl::identity<mpl::_> >,
                          0>::type actual_type;
                  
                      // type of boost::get we use
                      typedef actual_type& (*get_type)(variant_type&);
                  
                  // prints _2 if n is 0
                  #define PLACEHOLDER_print(z, n, unused) BOOST_PP_CAT(_, BOOST_PP_ADD(n, 2))
                  #define GET_print(z, n, unused)                                         
                      template<typename U>                                                
                      static variant_call_type get(                                       
                          typename boost::enable_if_c<fn::function_arity<U>::value ==     
                              BOOST_PP_INC(n), U>::type t                                 
                          ) {                                                             
                          /* (boost::get<actual_type>(some_variant).*t)(n1,...,nN) */     
                          return boost::bind(                                             
                              t, boost::bind(                                             
                                  (get_type)&boost::get<actual_type>,                     
                                  _1) BOOST_PP_ENUM_TRAILING(n, PLACEHOLDER_print, ~)     
                              );                                                          
                      }
                  
                  // generate functions for up to 8 parameters
                  BOOST_PP_REPEAT(9, GET_print, ~)
                  
                  #undef GET_print
                  #undef PLACEHOLDER_print
                  
                  };
                  
                  }
                  
                  // incoming type T is a member function type. we return a boost::bind object that
                  // will call boost::get on the variant passed and calls the member function
                  template<typename T>
                  variant_call_type make_caller(T t) {
                      return detail::build_caller<T>::template get<T>(t);
                  }
                  
                  // actions stuff. maps an id to a class and method.
                  typedef std::map<std::string, 
                                   std::pair< std::string, std::string >
                                   > actions_type;
                  
                  // this map maps (class, method) => (factory, function pointer)
                  typedef variant_type (*factory_function)();
                  typedef std::map< std::pair<std::string,      std::string>, 
                                    std::pair<factory_function, variant_call_type> 
                                    > class_method_map_type;
                  
                  // this will be our test function. it's supplied with the actions map, 
                  // and the factory map
                  std::string test(std::string const& id,
                                   actions_type& actions, class_method_map_type& factory) {
                      // pair containing the class and method name to call
                      std::pair<std::string, std::string> const& class_method =
                          actions[id];
                  
                      // real code should take the maps by const parameter and use
                      // the find function of std::map to lookup the values, and store
                      // results of factory lookups. we try to be as short as possible. 
                      variant_type v(factory[class_method].first());
                  
                      // execute the function associated, giving it the object created
                      return factory[class_method].second(v);
                  }
                  
                  int main() {
                      // possible actions
                      actions_type actions;
                      actions["first"] = std::make_pair("foo", "one");
                      actions["second"] = std::make_pair("bar", "two");
                      actions["third"] = std::make_pair("baz", "three");
                  
                      // connect the strings to the actual entities. This is the actual
                      // heart of everything.
                      class_method_map_type factory_map;
                      factory_map[actions["first"]] = 
                          std::make_pair(&factory<foo>, make_caller(&foo::one));
                      factory_map[actions["second"]] = 
                          std::make_pair(&factory<bar>, make_caller(&bar::two));
                      factory_map[actions["third"]] = 
                          std::make_pair(&factory<baz>, make_caller(&baz::three));
                  
                      // outputs "I am happy!"
                      std::cout << test("first", actions, factory_map)
                                << test("second", actions, factory_map)
                                << test("third", actions, factory_map) << std::endl;
                  }
                  

                  它使用了來自 boost 預處理器、函數類型和綁定庫的非常有趣的技術.可能循環復雜,但如果您獲得該代碼中的鍵,就不再需要掌握了.如果你想改變參數數量,你只需要調整 variant_call_type:

                  It uses pretty fun techniques from boost preprocessor, function types and bind library. Might loop complicated, but if you get the keys in that code, it's not much to grasp anymore. If you want to change the parameter count, you just have to tweak variant_call_type:

                  typedef boost::function<return_type (variant_type&, int)> variant_call_type;
                  

                  現在您可以調用帶有 int 的成員函數.以下是呼叫方的外觀:

                  Now you can call member functions that take an int. Here is how the call side would look:

                  return factory[class_method].second(v, 42);
                  

                  玩得開心!

                  如果你現在說以上太復雜了,我不得不同意你的看法.它很復雜,因為C++不是真正為這種動態使用而生的.如果可以在要創建的每個對象中對方法進行分組和實現,則可以使用純虛函數.或者,您可以在默認實現中拋出一些異常(如 std::runtime_error),因此派生類不需要實現所有內容:

                  If you now say the above is too complicated, i have to agree with you. It is complicated because C++ is not really made for such dynamic use. If you can have your methods grouped and implemented in each object you want create, you can use pure virtual functions. Alternatively, you could throw some exception (like std::runtime_error) in the default implementation, so derived classes do not need to implement everything:

                  struct my_object {
                      typedef std::string return_type;
                  
                      virtual ~my_object() { }
                      virtual std::string one() { not_implemented(); }
                      virtual std::string two() { not_implemented(); }
                  private:
                     void not_implemented() { throw std::runtime_error("not implemented"); }
                  };
                  

                  對于創建對象,通常的工廠就可以

                  For creating objects, a usual factory will do

                  struct object_factory {
                      boost::shared_ptr<my_object> create_instance(std::string const& name) {
                          // ...
                      }
                  };
                  

                  映射可以由映射 ID 到一對類和函數名稱(與上面相同)的映射以及映射到 boost::function 的映射組成:

                  The map could be composed by a map mapping IDs to a pair of class and function name (the same like above), and a map mapping that to a boost::function:

                  typedef boost::function<my_object::return_type(my_object&)> function_type;
                  typedef std::map< std::pair<std::string, std::string>, function_type> 
                                    class_method_map_type;
                  class_method_map[actions["first"]] = &my_object::one;
                  class_method_map[actions["second"]] = &my_object::two;
                  

                  調用函數的方式如下:

                  boost::shared_ptr<my_object> p(get_factory().
                      create_instance(actions["first"].first));
                  std::cout << class_method_map[actions["first"]](*p);
                  

                  當然,使用這種方法,您會失去靈活性和(可能尚未分析)效率,但您可以大大簡化您的設計.

                  Of course, with this approach, you loose flexibility and (possibly, haven't profiled) efficiency, but you greatly simplify your design.

                  這篇關于在 C++ 中動態創建和調用類方法的最簡單方法是什么?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

                  【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

                  相關文檔推薦

                  read input files, fastest way possible?(讀取輸入文件,最快的方法?)
                  The easiest way to read formatted input in C++?(在 C++ 中讀取格式化輸入的最簡單方法?)
                  Reading from .txt file into two dimensional array in c++(從 .txt 文件讀取到 C++ 中的二維數組)
                  How to simulate a key press in C++(如何在 C++ 中模擬按鍵按下)
                  Why doesn#39;t getline(cin, var) after cin.ignore() read the first character of the string?(為什么在 cin.ignore() 之后沒有 getline(cin, var) 讀取字符串的第一個字符?)
                  What is the cin analougus of scanf formatted input?(scanf 格式輸入的 cin 類比是什么?)
                2. <i id='uztHF'><tr id='uztHF'><dt id='uztHF'><q id='uztHF'><span id='uztHF'><b id='uztHF'><form id='uztHF'><ins id='uztHF'></ins><ul id='uztHF'></ul><sub id='uztHF'></sub></form><legend id='uztHF'></legend><bdo id='uztHF'><pre id='uztHF'><center id='uztHF'></center></pre></bdo></b><th id='uztHF'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='uztHF'><tfoot id='uztHF'></tfoot><dl id='uztHF'><fieldset id='uztHF'></fieldset></dl></div>
                    <tbody id='uztHF'></tbody>

                    <bdo id='uztHF'></bdo><ul id='uztHF'></ul>

                    <small id='uztHF'></small><noframes id='uztHF'>

                    <legend id='uztHF'><style id='uztHF'><dir id='uztHF'><q id='uztHF'></q></dir></style></legend><tfoot id='uztHF'></tfoot>

                          1. 主站蜘蛛池模板: av色噜噜 | 成人免费视屏 | 91麻豆精品国产91久久久更新资源速度超快 | 日韩精品在线一区 | 一区二区三区亚洲精品国 | 亚洲三区在线观看 | 人人草天天草 | 成年人网站在线观看视频 | 国产成人艳妇aa视频在线 | 美人の美乳で授乳プレイ | 日本高清视频在线播放 | 国产成人久久av免费高清密臂 | 97国产精品 | 国产91久久久久久久免费 | 成人在线观看黄 | 久久精品亚洲精品国产欧美 | 毛片一区 | 日韩影音 | 日韩成人中文字幕 | 麻豆精品国产91久久久久久 | 亚洲精品国产偷自在线观看 | 精品国产乱码久久久久久蜜柚 | 欧美成人一区二区三区 | 天堂亚洲网 | 亚洲视频中文字幕 | 免费黄色录像片 | 在线视频中文字幕 | 免费国产黄 | 欧洲毛片 | 91网站在线观看视频 | 欧美日韩一卡 | 人人九九精 | 成人久久久 | 欧美一级在线 | 亚洲人人| av香蕉| 91伊人| 日韩成人在线观看 | 波多野结衣中文字幕一区二区三区 | 国产精品综合色区在线观看 | 久久久亚洲成人 |