运行时类型信息(RTTI) C++中通过<typeinfo> 和 <typeindex> 头文件提供了运行时类型信息(RTTI)的支持,主要用于类型识别和类型比较。
1. <typeinfo> 提供运行时类型信息(RTTI),主要包含:
typeid 运算符:获取类型的 type_info 对象 
type_info 类:包含类型信息 
 
示例一:基本类型检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int  i = 42 ;   double  d = 3.14 ;    std::cout << "i is of type: "  << typeid (i).name () << '\n' ;    std::cout << "d is of type: "  << typeid (d).name () << '\n' ;    if  (typeid (i) == typeid (int ))    {        std::cout << "i is definitely an int\n" ;    }    if  (typeid (d) == typeid (double ))    {        std::cout << "d is definitely a double\n" ;    } 
 
示例二:多态类型检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class  Base {   public :     virtual  ~Base ()     {     } }; class  Derived  : public  Base{ }; int  main ()  {    Base* b = new  Derived ();     std::cout << "Actual type of b is: "  << typeid (*b).name () << std::endl;     delete  b;     return  0 ; } 
 
2.<typeindex> 提供std::type_index的类,是type_info的包装类,可以用作关联容器的键
示例三:在map中使用类型索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include  <iostream>  #include  <typeinfo>  #include  <typeindex>  #include  <unordered_map>  #include  <string>  int  main ()  {    std::unordered_map<std::type_index, std::string> type_names;     type_names[std::type_index (typeid (int ))] = "int" ;     type_names[std::type_index (typeid (double ))] = "double" ;     type_names[std::type_index (typeid (std::string))] = "string" ;     int  x;     double  y;     std::string z;     std::cout << "x is a "  << type_names[std::type_index (typeid (x))] << '\n' ;     std::cout << "y is a "  << type_names[std::type_index (typeid (y))] << '\n' ;     std::cout << "z is a "  << type_names[std::type_index (typeid (z))] << '\n' ; } 
 
Actor设计模式 actor通过消息传递的方式与外界通信。消息传递是异步的。每个actor都有一个邮箱,该邮箱接收并缓存其他actor发过来的消息,actor一次只能同步处理一个消息,处理消息过程中,除了可以接收消息,不能做任何其他操作。 每一个类独立在一个线程里称作Actor,Actor之间通过队列通信,比如Actor1 发消息给Actor2, Actor2 发消息给Actor1都是投递到对方的队列中。好像给对方发邮件,对方从邮箱中取出一样。如下图
Actor模型的另一个好处就是可以消除共享状态,因为它每次只能处理一条消息,所以actor内部可以安全的处理状态,而不用考虑锁机制。
Actor在C++中的简单实现: 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 #ifndef  ACTOR_H #define  ACTOR_H #include  <chrono>  #include  <condition_variable>  #include  <exception>  #include  <functional>  #include  <iostream>  #include  <memory>  #include  <mutex>  #include  <queue>  #include  <stdexcept>  #include  <string>  #include  <thread>  #include  <typeinfo>  #include  <unordered_map>  #include  <utility>  #include  <atomic>  namespace  actor{ class  Message {   public :     virtual  ~Message ()     {     }     virtual  std::string type ()  const   = 0 ;     virtual  std::string toString ()  const       {        return  type ();     } }; template  <typename  Derived>class  TypedMessage  : public  Message{   public :     std::string type ()  const  override        {        return  typeid (Derived).name ();     } }; struct  TextMessage  : public  TypedMessage<TextMessage>{     std::string content;     explicit  TextMessage (std::string c)  : content(std::move(c))     {     }     std::string toString ()  const  override        {        return  "TextMessage: "  + content;     } }; struct  StopMessage  : public  TypedMessage<StopMessage>{     std::string toString ()  const  override        {        return  "StopMessage" ;     } }; struct  TimeoutMessage  : public  TypedMessage<TimeoutMessage>{     std::string toString ()  const  override        {        return  "TimeoutMessage" ;     } }; using  MessagePtr = std::shared_ptr<Message>;class  Actor  : public  std::enable_shared_from_this<Actor>{     friend  class  ActorSystem ;   public :     Actor () : running_ (true )     {     }     virtual  ~Actor ()     {         if  (thread_.joinable ())             thread_.join ();     }     void  start ()       {        thread_ = std::thread (&Actor::run, this );         std::cout << "["  << name_ << "] started."  << std::endl;     }     template  <typename  T, typename ... Args>     void  send (Args&&... args)       {        auto  msg = std::make_shared <T>(std::forward<Args>(args)...);         {             std::lock_guard<std::mutex> lock (mutex_)  ;             mailbox_.push (msg);         }         cv_.notify_all ();     }     void  send (MessagePtr msg)       {        {             std::lock_guard<std::mutex> lock (mutex_)  ;             mailbox_.push (msg);         }         cv_.notify_all ();     }     template  <typename  T, typename ... Args>     void  sendAfter (std::chrono::milliseconds delay, Args&&... args)       {        std::weak_ptr<Actor> weakSelf = shared_from_this ();         std::thread (             [weakSelf, delay, args...]()             {                 std::this_thread::sleep_for (delay);                 if  (auto  self = weakSelf.lock ())                 {                     self->send <T>(args...);                 }             })             .detach ();     }     void  setName (const  std::string& name)       {        name_ = name;     }     std::string getName ()  const        {        return  name_;     }     void  setProcessTimeout (std::chrono::milliseconds timeout)       {        process_timeout_ = timeout;     }          void  join ()       {        if  (thread_.joinable ())             thread_.join ();     }   protected :     virtual  void  onMessage (MessagePtr msg)   = 0 ;     virtual  void  onTimeout ()       {        send <TimeoutMessage>();     }     virtual  void  onStop ()       {    }     virtual  void  onStart ()       {    }   private :     void  run ()       {        onStart ();         while  (running_)         {             MessagePtr msg;             {                 std::unique_lock<std::mutex> lock (mutex_)  ;                 if  (cv_.wait_for (lock, process_timeout_, [&]() { return  !mailbox_.empty (); }))                 {                     msg = mailbox_.front ();                     mailbox_.pop ();                 }                 else                  {                     onTimeout ();                     continue ;                 }             }             std::cout << "["  << name_ << "] received message: "  << msg->toString () << std::endl;             if  (std::dynamic_pointer_cast <StopMessage>(msg))             {                 std::cout << "["  << name_ << "] stopping by StopMessage."  << std::endl;                 running_ = false ;                 break ;             }             try              {                 onMessage (std::move (msg));             }             catch  (const  std::exception& e)             {                 std::cerr << "Exception in "  << name_ << ": "  << e.what () << std::endl;             }         }         onStop ();         std::cout << "["  << name_ << "] stopped."  << std::endl;     }          void  stop ()       {        if  (running_)         {             send <StopMessage>();             running_ = false ;          }     }   private :     std::atomic<bool > running_;     std::thread thread_;     std::queue<MessagePtr> mailbox_;     std::mutex mutex_;     std::condition_variable cv_;     std::string name_;     std::chrono::milliseconds process_timeout_{1000 }; }; class  ActorSystem {   public :     ~ActorSystem ()     {         shutdown ();     }     template  <typename  T, typename ... Args>     std::shared_ptr<T> createActor (const  std::string& name, Args&&... args)        {        auto  actor = std::make_shared <T>(std::forward<Args>(args)...);         registerActor (name, actor);         actor->start ();         return  actor;     }     void  registerActor (const  std::string& name, std::shared_ptr<Actor> actor)       {        std::lock_guard<std::mutex> lock (mutex_)  ;         if  (actors_.count (name))             throw  std::runtime_error ("Actor already exists: "  + name);         actor->setName (name);         actors_[name] = actor;     }     std::shared_ptr<Actor> getActor (const  std::string& name)        {        std::lock_guard<std::mutex> lock (mutex_)  ;         auto  it = actors_.find (name);         return  (it != actors_.end ()) ? it->second : nullptr ;     }     void  broadcast (MessagePtr msg)       {        std::lock_guard<std::mutex> lock (mutex_)  ;         for  (auto & [_, actor] : actors_)             actor->send (msg);     }     void  shutdown ()       {        std::cout << "begin shutdown"  << std::endl;         {             std::lock_guard<std::mutex> lock (mutex_)  ;             for  (auto & [_, actor] : actors_)                 actor->send <StopMessage>();         }                  {             std::lock_guard<std::mutex> lock (mutex_)  ;             for  (auto & [_, actor] : actors_)                 actor->join ();             actors_.clear ();         }         std::cout << "shutdown finished"  << std::endl;     }   private :     std::unordered_map<std::string, std::shared_ptr<Actor>> actors_;     std::mutex mutex_; }; }  #endif   
 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include  "actor_system.h"  #include  <iostream>  using  namespace  actor;class  Printer  : public  Actor{   protected :     void  onMessage (MessagePtr msg)  override       {        if  (auto  text = std::dynamic_pointer_cast <TextMessage>(msg))         {             std::cout << "[printer] "  << text->content << std::endl;         }     } }; class  Pinger  : public  Actor{   public :     Pinger (ActorSystem& system) : system_ (system)     {     }   protected :     void  onStart ()  override       {        send <TextMessage>("Ping" );     }     void  onMessage (MessagePtr msg)  override       {        if  (auto  text = std::dynamic_pointer_cast <TextMessage>(msg))         {             std::cout << "[pinger] received: "  << text->content << std::endl;             if  (text->content == "Ping" )             {                                  auto  printer = system_.getActor ("printer" );                 if  (printer)                 {                     printer->send <TextMessage>("Ping!" );                 }             }         }     }   private :     ActorSystem& system_; }; int  main ()  {    ActorSystem system;     auto  printer = system.createActor <Printer>("printer" );     auto  pinger = system.createActor <Pinger>("pinger" , std::ref (system));     std::this_thread::sleep_for (std::chrono::seconds (1 ));     system.shutdown ();     return  0 ; }