{"id":339627,"date":"2022-10-13T09:00:14","date_gmt":"2022-10-13T09:00:14","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=339627"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=339627","title":{"rendered":"<span>\u0415\u0441\u0442\u044c \u043b\u0438 \u0436\u0438\u0437\u043d\u044c \u0431\u0435\u0437 RTTI: \u043f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439 dynamic_cast<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c \u0421++ \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0432\u0435\u0449\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u043f\u043e\u0434 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0443 &#171;\u041d\u0435 \u043f\u043b\u0430\u0442\u0438 \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0448\u044c&#187;. \u041e\u0434\u043d\u0430 \u0438\u0437 \u043d\u0438\u0445 \u2013 dynamic_cast. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f, \u0447\u0442\u043e \u0441 \u043d\u0438\u043c \u043d\u0435 \u0442\u0430\u043a, \u0430 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0439\u043c\u0451\u043c \u2013 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0443.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b57\/14b\/5bb\/b5714b5bb8ef872ac589c5d888a3d26a.png\" width=\"975\" height=\"550\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b57\/14b\/5bb\/b5714b5bb8ef872ac589c5d888a3d26a.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u041e\u0431 \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0437\u043e\u0432 \u044f\u0437\u044b\u043a\u0430 C++. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043f\u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0441\u043a\u0443\u0447\u043d\u043e\u0439 \u044d\u0442\u0430 \u0447\u0430\u0441\u0442\u044c, \u0432\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0433\u043b\u0430\u0432\u0435.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<pre><code class=\"cpp\">struct Shape {   virtual void Draw() const = 0; };  struct Circle : Shape {   void Draw() const override; };  struct Triangle : Shape {   void Draw() const override; };  struct Rectangle : Shape {   void Draw() const override; }; <\/code><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435 \u043c\u044b \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c &#171;\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u0435&#187; \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f (<em>upcasting<\/em>) \u0438\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043a \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044e \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"cpp\">#include &lt;memory>  void foo(const Shape *);  void bar() {   std::unique_ptr&lt;Shape>   circle = std::make_unique&lt;Circle>();   std::unique_ptr&lt;Shape> triangle = std::make_unique&lt;Triangle>();   std::unique_ptr&lt;Shape>     rect = std::make_unique&lt;Rectangle>();    foo(circle.get());   foo(triangle.get());   foo(rect.get()); } <\/code><\/pre>\n<p>\u0422.\u043a. \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b <em>Circle<\/em>, <em>Triangle<\/em> \u0438 <em>Rectangle<\/em> \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441 <em>Shape<\/em>, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<p>\u0410 \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0432 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0439? \u041f\u043e\u0434 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c \u043d\u0430 <em>Shape<\/em> \u043c\u043e\u0436\u0435\u0442 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0439 \u043e\u0442 \u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441. \u041d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0436\u0435 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c. \u0422\u0443\u0442 \u043d\u0430 \u0441\u0446\u0435\u043d\u0443 \u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 (<em>runtime type identification<\/em>, \u0441\u043e\u043a\u0440. <em>RTTI<\/em>).<\/p>\n<p>RTTI \u2013 \u044d\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. \u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c RTTI \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u0441\u044f\u043a\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/dynamic_cast\"><em>dynamic_cast<\/em><\/a> \u0438 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/typeid\"><em>typeid<\/em><\/a>. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++ \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f RTTI, \u0438 \u0432\u0441\u044f \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <em>\u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439<\/em> (<em>application binary interface<\/em>, \u0441\u043e\u043a\u0440. <em>ABI<\/em>). \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 (<em>vtable<\/em>). \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b \u0434\u0435\u0442\u0430\u043b\u0438, \u0442\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 <a href=\"https:\/\/itanium-cxx-abi.github.io\/cxx-abi\/abi.html#rtti\">x86_64<\/a>.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 &#171;\u0441\u0443\u0436\u0430\u044e\u0449\u0438\u0435&#187; \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f (<em>downcasting<\/em>) \u0438\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043a \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044e \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c <em>dynamic_cast<\/em>:<\/p>\n<pre><code class=\"cpp\">void Visit(const Shape *ptr) {   if (auto circle = dynamic_cast&lt;const Circle *>(ptr))   {     \/\/ do smth with circle   }   else if (auto triangle = dynamic_cast&lt;const Triangle *>(ptr))   {     \/\/ do smth with triangle   }   else if (auto rect = dynamic_cast&lt;const Rectangle *>(ptr))   {     \/\/ do smth with rect   } } <\/code><\/pre>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, <em>dynamic_cast<\/em> \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u043a\u043e\u0434\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u0442\u0430\u043a \u0447\u0430\u0441\u0442\u043e, <em>typeid<\/em> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0435\u0449\u0435 \u0440\u0435\u0436\u0435. \u041a\u0442\u043e-\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u2013 \u0441\u0438\u043c\u043f\u0442\u043e\u043c \u043f\u043b\u043e\u0445\u043e\u0433\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u0430\u043a \u043e\u0431\u0441\u0442\u043e\u044f\u0442 \u0434\u0435\u043b\u0430 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0430\u043a\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u2013 \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u043d\u0430\u044f \u043c\u0435\u0440\u0430, \u0438 \u0438\u0445 \u0447\u0438\u0441\u043b\u043e \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430\u043c\u0438? \u041d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0438 \u044d\u0442\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u2013 \u0441\u043b\u0430\u0437\u0438\u0442\u044c \u0432 <em>vtable<\/em>? \u041e\u0431 \u044d\u0442\u043e\u043c \u043c\u044b \u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c.<\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u043a\u0430<\/h3>\n<p>\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u044b, \u043a\u0430\u043a \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0435\u0433\u043e \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u043e \u0438\u0437 \u043d\u0438\u0445 \u2013 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e (AST). \u0412 \u043d\u0451\u043c \u0443\u0437\u043b\u044b \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0432 \u0440\u043e\u043b\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439.<\/p>\n<p>\u0423\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c AST \u0432 \u043a\u043e\u0434\u0435 \u2013 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 Clang \u0443\u0437\u043b\u044b \u0434\u0435\u0440\u0435\u0432\u0430 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442\u0441\u044f \u043e\u0442 \u0442\u0430\u043a\u0438\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043a\u0430\u043a <a href=\"https:\/\/clang.llvm.org\/doxygen\/classclang_1_1Decl.html\"><em>Decl<\/em><\/a> (\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438 \u0442\u0438\u043f\u043e\u0432) \u0438 <a href=\"https:\/\/clang.llvm.org\/doxygen\/classclang_1_1Stmt.html\"><em>Stmt<\/em><\/a> (\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439).<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"cpp\">{   for (size_t i = 0; i &lt; 10; ++i) ;   if (true) ; } <\/code><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430\u043c \u044f\u0437\u044b\u043a\u043e\u0432 <a href=\"https:\/\/en.cppreference.com\/w\/c\/language\/statements\">C<\/a> \u0438 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/statements\">C++<\/a>, \u044d\u0442\u043e \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f (\u0431\u043b\u043e\u043a), \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0446\u0438\u043a\u043b <em>for<\/em> \u0438 \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 <em>if<\/em>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435, \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"cpp\">\/\/ Base class for all type of statements struct Stmt { \/* .... *\/ };  \/\/ Base class for all type of expressions struct Expr { \/* .... *\/ };  \/\/ Base class for all types of declarations struct Decl { \/* .... *\/ };  struct IfStmt : Stmt {   const Expr&amp; GetCondition() const noexcept;   const Stmt&amp; GetBody()      const noexcept;   const Stmt* GetElse()      const noexcept;    \/\/ .... };  struct ForStmt : Stmt {   const Decl* GetInit()         const noexcept;   const Expr* GetCondition()    const noexcept;   const Expr* GetPostBodyExpr() const noexcept;   const Stmt&amp; GetBody()         const noexcept;    \/\/ .... };  using StatementList = ....;  struct CompoundStmt : Stmt {   auto begin() const noexcept { return stmts.begin(); }   auto end() const noexcept { return stmts.end(); }    private:   StatementList stmts;    \/\/ .... }; <\/code><\/pre>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u043a\u043b\u0430\u0441\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <em>std::vector<\/em>. \u0422\u0430\u043a \u043a\u0430\u043a \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0432 \u044f\u0437\u044b\u043a\u0430\u0445 \u043d\u0438 \u043e\u0434\u043d\u0430 \u0438 \u0434\u0430\u0436\u0435 \u043d\u0435 \u0434\u0432\u0435, \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <em>Stmt<\/em>. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"cpp\">void foo(const CompoundStmt *compStmt) {   for (auto stmt : compStmt)   {     \/\/ do smth   } } <\/code><\/pre>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u0441\u0432\u043e\u044e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443:<\/p>\n<pre><code class=\"cpp\">void Visit(const IfStmt &amp;); void Visit(const ForStmt &amp;); <\/code><\/pre>\n<p>\u0418 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u2013 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043a\u0430\u043a\u0430\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u043f\u043e\u0434 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c \u043d\u0430 <em>Stmt<\/em> \u0438 \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0443:<\/p>\n<pre><code class=\"cpp\">void foo(const Stmt *stmt) {   for (auto stmt : compStmt)   {     if (auto ifStmt = dynamic_cast&lt;const IfStmt *>(stmt))     {       Visit(*ifStmt);     }     else if (auto forStmt = dynamic_cast&lt;const ForStmt *>(stmt))     {       Visit(*forStmt);     }   } } <\/code><\/pre>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u0442\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0430\u044f \u0434\u0435\u0442\u0430\u043b\u044c, \u0438\u0437-\u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043a\u043e\u0434 \u0432\u044b\u0448\u0435 <strong>\u043c\u043e\u0436\u0435\u0442<\/strong> \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f. \u0415\u0441\u043b\u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <em>Stmt<\/em> \u043d\u0435 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0435\u043d, \u0442\u043e \u043c\u0430\u0433\u0438\u044f <em>dynamic_cast<\/em> \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">struct Stmt { virtual void Dummy(); \/* .... *\/ }; <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432. \u041f\u043e\u043a\u0430 \u043d\u0435 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d RTTI. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430\u0445 GCC\/Clang \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0444\u043b\u0430\u0433 <em>-fno-rtti<\/em> (GCC, Clang), \u0432 MSVC \u2013 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c <em>\/GR-<\/em>. \u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 RTTI \u043d\u0435 \u0437\u0430\u0434\u0435\u0432\u0430\u0435\u0442 <a href=\"https:\/\/godbolt.org\/z\/zcso7rTcz\">\u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439<\/a> \u0438 <a href=\"https:\/\/godbolt.org\/z\/KeEM88vP9\">\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e<\/a>.<\/p>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u043f\u043e\u043a\u0430 \u0433\u043e\u0442\u043e\u0432\u0438\u043b \u0441\u0442\u0430\u0442\u044c\u044e, \u043d\u0430\u0448\u0451\u043b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043e\u043f\u0440\u043e\u0441 \u043d\u0430 <a href=\"https:\/\/isocpp.org\/files\/papers\/CppDevSurvey-2019-04-summary.pdf\">isocpp.org<\/a>. \u0412 \u043d\u0451\u043c \u0438\u0437 <em>2058<\/em> \u0440\u0435\u0441\u043f\u043e\u043d\u0434\u0435\u043d\u0442\u043e\u0432 <em>14%<\/em> \u043e\u0442\u0432\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u043e\u043d\u0438 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u044e\u0442 RTTI \u043d\u0430 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u0445, \u0430 <em>18%<\/em> \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0435\u0433\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<p>\u041f\u043e\u0434\u044b\u0442\u043e\u0436\u0438\u043c, <em>dynamic_cast<\/em> \u043f\u043b\u043e\u0445 \u0442\u0435\u043c, \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u044b\u0445 \u0442\u0438\u043f\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0444\u043b\u0430\u0433\u043e\u043c <em>-fno-rtti<\/em>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f ABI-\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u0438\u043f\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>&#171;\u0421\u0443\u0436\u0430\u044e\u0449\u0438\u0435&#187; \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 <em>vtable,<\/em> \u0430 \u044d\u0442\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f &#171;<a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9F%D0%BE%D1%81%D0%B5%D1%82%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)\">\u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044c<\/a>&#187; (\u0432\u0438\u0437\u0438\u0442\u043e\u0440). \u041e\u043d\u043e \u0438\u0437\u0431\u0430\u0432\u0438\u0442 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c <em>dynamic_cast<\/em> \u0446\u0435\u043d\u043e\u0439 \u043e\u0434\u043d\u043e\u0433\u043e-\u0434\u0432\u0443\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0438\u043d\u0430\u0447\u0435.<\/p>\n<h3>\u041f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439 dynamic_cast<\/h3>\n<h4>\u042d\u0442\u043e \u0431\u0430\u0437\u0430<\/h4>\n<p>\u0420\u0435\u0446\u0435\u043f\u0442 \u043b\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043f\u0440\u043e\u0441\u0442. \u041c\u044b \u0432\u043d\u0435\u0434\u0440\u0438\u043c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u0435 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u0442\u0438\u043f\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u0441\u0430\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0435\u0451. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">struct Stmt {    enum Type { IfStmt, ForStmt, DoStmt, WhileStmt, ....  };   const Type m_kind;   Stmt(Type kind) : m_kind { kind } { \/* .... *\/ }   \/* .... *\/ };  struct IfStmt : Stmt {   IfStmt() : Stmt { Stmt::Type::IfStmt } { \/* .... *\/ }   \/* .... *\/ };  struct ForStmt : Stmt {   ForStmt() : Stmt { Stmt::Type::ForStmt } { \/* .... *\/ }   \/* .... *\/ }; <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u044b \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0442\u0438\u043f \u0432 \u043f\u043e\u043b\u0435 <em>m_kind<\/em>. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u0438\u043f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cpp\">void foo(const Stmt *stmt) {   if (stmt->m_kind == Stmt::Type::IfStmt)   {     auto ifStmt = static_cast&lt;const IfStmt *>(stmt)     Visit(*ifStmt);   }   else if (stmt->m_kind == Stmt::Type::ForStmt)   {     auto forStmt = static_cast&lt;const ForStmt *>(stmt)     Visit(*forStmt);   } } <\/code><\/pre>\n<p>\u0418\u0437 \u043f\u043b\u044e\u0441\u043e\u0432 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u043e\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0435\u0437 RTTI.<\/p>\n<\/li>\n<li>\n<p>\u041c\u044b \u0441\u0430\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u0438\u043f\u0435. \u0423 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u2013 \u044d\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0411\u044b\u0441\u0442\u0440\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <em>static_cast<\/em> \u0432 \u0442\u0435\u043e\u0440\u0438\u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <em>dynamic_cast<\/em>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e, \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0438 \u043c\u0438\u043d\u0443\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u041c\u044b \u043f\u0438\u0448\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p><em>static_cast<\/em> \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <a href=\"https:\/\/godbolt.org\/z\/Kb175eh4E\">\u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c<\/a> \u0438 \u043a\u043e\u0434 \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041d\u043e \u043c\u043d\u043e\u0433\u043e \u043b\u0438 \u043b\u044e\u0434\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 2022 \u0433\u043e\u0434\u0443?<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u043d\u0430 \u043a\u043e\u0434, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c &#171;\u0410 \u0433\u0434\u0435 \u0437\u0434\u0435\u0441\u044c \u0430\u043d\u0430\u043b\u043e\u0433 <em>dynamic_cast<\/em>&#171;? \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e. \u0427\u0442\u043e\u0431 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0439. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0443 \u043d\u0430\u0441 \u0432 PVS-Studio \u0438 \u0432 LLVM.<\/p>\n<h4>\u041d\u0430\u0432\u043e\u0434\u0438\u043c \u043a\u0440\u0430\u0441\u043e\u0442\u0443. \u041f\u043e\u0434\u0445\u043e\u0434 \u0432 PVS-Studio<\/h4>\n<p>\u0412\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043c\u0435\u0440\u0443:<\/p>\n<pre><code class=\"cpp\">struct Stmt {    enum Type { IfStmt, ForStmt, DoStmt, WhileStmt, ....  };   Stmt(Type kind) : m_kind { kind } { \/* .... *\/ }   Type Kind() const { return m_kind; } private:   const Type m_kind;   \/* .... *\/ }; <\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <em>IsA<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0448 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f. \u0412\u043d\u0443\u0442\u0440\u0438 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0438 \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0439 <em>kind<\/em>.<\/p>\n<pre><code class=\"cpp\">template &lt;typename T, typename Kind> bool IsA(T *p, Kind kind) noexcept {   return p &amp;&amp; p->Kind() == kind; } <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0430\u0440\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0431\u0435\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"cpp\">template &lt;Stmt::Type K> struct type_from_kind;  template &lt;typename T> struct kind_from_type; <\/code><\/pre>\n<p>\u041e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0441\u0432\u044f\u0436\u0435\u043c \u0442\u0438\u043f \u0443\u0437\u043b\u0430 \u0434\u0435\u0440\u0435\u0432\u0430 \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0443\u044e\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<pre><code class=\"cpp\">template &lt;> struct type_from_kind&lt;Stmt::IfStmt> {   using type = IfStmt; };  template &lt;> struct kind_from_type&lt;IfStmt> {   static constexpr auto value = Stmt::Type::IfStmt; }; <\/code><\/pre>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u0438\u044f\u0442\u043d\u043e. \u0422\u0443\u0442 \u043d\u0430\u043c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0439\u0442\u0438 &#171;\u043c\u0430\u043a\u0440\u043e\u0441\u043d\u0430\u044f \u043c\u0430\u0433\u0438\u044f&#187;:<\/p>\n<pre><code class=\"cpp\">#define MAKE_STMT_TRAITS(t, k) \\   template &lt;> struct type_from_kind&lt;k> \\   { \\     using type = t; \\   }; \\    template &lt;> struct kind_from_type&lt;t> \\   { \\     static constexpr auto value = k; \\   }; <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">struct IfStmt : Stmt { \/* .... *\/ }; MAKE_STMT_TRAITS(IfStmt, Stmt::IfStmt)  struct ForStmt : Stmt { \/* .... *\/ }; MAKE_STMT_TRAITS(ForStmt, Stmt::ForStmt) <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 <em>dyn_cast<\/em>, \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 <em>static_cast<\/em> c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0439 \u0442\u0438\u043f \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>IsA<\/em>:<\/p>\n<pre><code class=\"cpp\">template &lt;typename To, typename From>   requires std::is_pointer_v&lt;To> &amp;&amp; std::convertible_to&lt;From, To> auto dyn_cast(From *p) noexcept {   using ResultType = std::remove_cvref_t&lt;std::remove_pointer_t&lt;To>>;   return IsA(p, kind_from_type&lt;ResultType>::value)            ? static_cast&lt;To>(p)            : nullptr; } <\/code><\/pre>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0442\u0430\u043a\u043e\u043c\u0443 \u043f\u043e\u0434\u0445\u043e\u0434\u0443 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0441\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0441\u0430\u043b\u0438 <em>dynamic_cast<\/em>:<\/p>\n<pre><code class=\"cpp\">void foo(const Stmt *stmt) {   for (auto stmt : compStmt)   {     if (auto ifStmt = dyn_cast&lt;const IfStmt *>(stmt))     {       Visit(*ifStmt);     }     else if (auto forStmt = dyn_cast&lt;const ForStmt *>(stmt))     {       Visit(*forStmt);     }   } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431.<\/p>\n<h4>\u041d\u0430\u0432\u043e\u0434\u0438\u043c \u043a\u0440\u0430\u0441\u043e\u0442\u0443. \u041f\u043e\u0434\u0445\u043e\u0434 \u0432 LLVM<\/h4>\n<p>\u0412\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 <em>Stmt<\/em>:<\/p>\n<pre><code class=\"cpp\">struct Stmt {    enum Type { IfStmt, ForStmt, DoStmt, WhileStmt, ....  };   Stmt(Type kind) : m_kind { kind } { \/* .... *\/ }   Type Kind() const { return m_kind; } private:   const Type m_kind;   \/* .... *\/ }; <\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0441-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a \u043c\u044b \u0432\u043d\u0435\u0434\u0440\u044f\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u0447\u043b\u0435\u043d <em>classof<\/em>. \u041e\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0435\u0433\u043e \u043d\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0441 kind \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"cpp\">struct IfStmt : Stmt {   static bool classof(const Stmt *stmt) noexcept   {     return stmt->Kind() == Stmt::Type::IfStmt;   }   \/* .... *\/ };  struct ForStmt : Stmt {   static bool classof(const Stmt *stmt) noexcept   {     return stmt->Kind() == Stmt::Type::ForStmt;   }   \/* .... *\/ }; <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <em>IsA<\/em> \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0437\u0432\u0430\u0442\u044c <em>classof<\/em> \u0438\u0437 \u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c:<\/p>\n<pre><code class=\"cpp\">template &lt;typename To, typename From> bool IsA(From *p) noexcept {   using ResultType = std::remove_cvref_t&lt;     std::remove_pointer_t&lt; std::remove_cv_ref_t&lt;To> >   >;    return ResultType::classof(p); } <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043d\u0430\u0448 <em>dyn_cast<\/em> \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 <em>IsA<\/em>, \u043a\u0430\u043a \u0438 \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u0435, \u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0441\u043e\u0432\u043f\u0430\u043b \u0442\u0438\u043f \u0438\u043b\u0438 \u043d\u0435\u0442, \u0434\u0435\u043b\u0430\u0442\u044c <em>static_cast<\/em> \u043a \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443 \u0438\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c:<\/p>\n<pre><code class=\"cpp\">template &lt;typename To, typename From>   requires std::is_pointer_v&lt;To> &amp;&amp; std::convertible_to&lt;From *, To> auto dyn_cast(From *p) noexcept {   using res_type = std::remove_cv_t &lt;      std::remove_pointer_t&lt; std::remove_cvref_t&lt;To> >   >;     return IsA&lt;res_type>(p) ? static_cast&lt;To>(p) : nullptr; } <\/code><\/pre>\n<h3>\u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438<\/h3>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438 \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438, \u044f \u043f\u0440\u0438\u0432\u0451\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b. \u0411\u044b\u043b\u043e \u043f\u043e\u0434\u043e\u0437\u0440\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u044d\u0442\u043e \u0436\u0435 \u043e\u0442\u043c\u0435\u0442\u0438\u043b \u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043e\u043b\u043b\u0435\u0433. \u0411\u044b\u043b \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e, \u043d\u0435 \u0437\u043d\u0430\u044f, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u0451\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431, \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u043d\u0435\u0433\u043e \u043a\u043e\u0434. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0441\u044c \u0438 \u043f\u0440\u0438\u0432\u043e\u0436\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443, \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043c\u0435\u0434\u043b\u0438\u0442\u0441\u044f \u044f\u0434\u0440\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430, \u0435\u0441\u043b\u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c <em>dynamic_cast<\/em>.<\/p>\n<h4>\u0421\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/h4>\n<p>\u0421\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c (<a href=\"https:\/\/quick-bench.com\/q\/v-3hraub6v8nlitjtx8ybgDT7PA\">\u0441\u0441\u044b\u043b\u043a\u0430<\/a> \u043d\u0430 Quick C++ Benchmark):<\/p>\n<ol>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 <em>Stmt_RTTI<\/em>, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b <em>IfStmt_RTTI<\/em> \u0438 <em>ForStmt_RTTI<\/em>. \u0418\u0445 \u043c\u044b \u0432\u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <em>dynamic_cast.<\/em><\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 <em>Stmt_WithEnum<\/em>, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f <em>IfStmt_WithEnum<\/em> \u0438 <em>ForStmt_WithEnum<\/em>. \u0418\u0445 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <em>IsA<\/em>, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0434\u0432\u0443\u043c\u044f \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438, \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <em>static_cast<\/em>.<\/p>\n<\/li>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0432\u0435\u043a\u0442\u043e\u0440 \u0438\u0437 1&#8217;000&#8217;000 \u0443\u043c\u043d\u044b\u0445 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0442\u0438\u043f <em>Stmt_RTTI<\/em> \/ <em>Stmt_WithEnum<\/em>, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0438\u0445 \u043f\u0441\u0435\u0432\u0434\u043e\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0442\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u043f\u043e \u0432\u0435\u043a\u0442\u043e\u0440\u0443 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0438\u0437 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0442\u0438\u043f\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<p>\u041a\u043e\u0434 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430:<\/p>\n<pre><code class=\"cpp\">#include &lt;memory> #include &lt;vector> #include &lt;random>  struct Stmt_RTTI { virtual ~Stmt_RTTI() = default; };  struct IfStmt_RTTI : Stmt_RTTI { }; struct ForStmt_RTTI : Stmt_RTTI { };  struct Stmt_WithEnum {    enum Type { IfStmt, ForStmt, DoStmt, WhileStmt };   Stmt_WithEnum(Type kind) : m_kind { kind } { }   virtual ~Stmt_WithEnum() = default;   Type Kind() const { return m_kind; }  private:   const Type m_kind; };  namespace Solution1 {   template &lt;Stmt_WithEnum::Type K>   struct type_from_kind;    template &lt;typename T>   struct kind_from_type;  #define MAKE_STMT_TRAITS(t, k) \\   template &lt;> struct Solution1::type_from_kind&lt;k> \\   { \\     using type = t; \\   }; \\   template &lt;> struct Solution1::kind_from_type&lt;t> \\   { \\     static constexpr auto value = k; \\   };    template &lt;typename T, typename Kind, typename ...Kinds>   bool IsA(T stmt, Kind kind, Kinds ...kinds) noexcept   {     return stmt &amp;&amp;           ((stmt->Kind() == kind) || ... || (stmt->Kind() == kinds));   }    template &lt;typename To, typename From>        requires std::is_pointer_v&lt;To>     &amp;&amp; requires { static_cast&lt;To>(std::declval&lt;From *>()); }   auto dyn_cast(From *p) noexcept   {     using ResultType = std::remove_cvref_t&lt;       std::remove_pointer_t&lt; std::remove_cvref_t&lt;To> >     >;      return IsA(p, kind_from_type&lt;ResultType>::value)              ? static_cast&lt;To>(p)              : nullptr;   } }  struct IfStmt_WithEnum : Stmt_WithEnum {   IfStmt_WithEnum() : Stmt_WithEnum { Stmt_WithEnum::IfStmt } {}     static bool classof(const Stmt_WithEnum *p) noexcept   {     return p &amp;&amp; p->Kind() == Stmt_WithEnum::IfStmt;   } };  MAKE_STMT_TRAITS(IfStmt_WithEnum, Stmt_WithEnum::IfStmt)  struct ForStmt_WithEnum : Stmt_WithEnum {   ForStmt_WithEnum() : Stmt_WithEnum { Stmt_WithEnum::ForStmt } {}    static bool classof(const Stmt_WithEnum *p) noexcept   {     return p &amp;&amp; p->Kind() == Stmt_WithEnum::ForStmt;   } };  MAKE_STMT_TRAITS(ForStmt_WithEnum, Stmt_WithEnum::ForStmt)  namespace Solution2 {   template &lt;typename To, typename From>   bool IsA(From *p) noexcept   {     using ResultType = std::remove_cvref_t&lt;       std::remove_pointer_t&lt; std::remove_cvref_t&lt;To> >     >;      return ResultType::classof(p);   }    template &lt;typename To, typename From>        requires std::is_pointer_v&lt;To>     &amp;&amp; requires { static_cast&lt;To>(std::declval&lt;From *>()); }   auto dyn_cast(From *p) noexcept   {     using ResultType = std::remove_cvref_t&lt;       std::remove_pointer_t&lt; std::remove_cvref_t&lt;To> >     >;      return IsA&lt;ResultType>(p) ? static_cast&lt;To>(p) : nullptr;   } }  std::unique_ptr&lt;Stmt_RTTI> factory_1() {   static std::mt19937_64 Generator { 0 };   std::uniform_int_distribution d { 0, 1 };   switch (d(Generator))   {   case 0:     return std::make_unique&lt;IfStmt_RTTI>();   case 1:     return std::make_unique&lt;ForStmt_RTTI>();   }    std::terminate(); }  std::unique_ptr&lt;Stmt_WithEnum> factory_2() {   static std::mt19937_64 Generator { 0 };   std::uniform_int_distribution d { 0, 1 };   switch (d(Generator))   {   case 0:     return std::make_unique&lt;IfStmt_WithEnum>();   case 1:     return std::make_unique&lt;ForStmt_WithEnum>();   }    std::terminate(); }  static void StmtRTTI_Benchmark(benchmark::State&amp; state) {   std::vector&lt;std::unique_ptr&lt;Stmt_RTTI>> vec;   const auto size = 1'000'000u;      vec.reserve(size);   for (size_t i = 0; i &lt; size; ++i)   {     vec.push_back(factory_1());   }    \/\/ Code inside this loop is measured repeatedly   for (auto _ : state)   {     for (const auto &amp;stmt : vec)     {       if (auto ifStmt = dynamic_cast&lt;const IfStmt_RTTI *>(stmt.get()))       {         \/\/ Make sure the variable is not optimized away by compiler         benchmark::DoNotOptimize(ifStmt);       }       else if (auto forStmt = dynamic_cast&lt;const ForStmt_RTTI *>(stmt.get()))       {         \/\/ Make sure the variable is not optimized away by compiler         benchmark::DoNotOptimize(forStmt);       }     }   } } \/\/ Register the function as a benchmark BENCHMARK(StmtRTTI_Benchmark);  static void StmtWithEnum_Benchmark_1(benchmark::State&amp; state) {   std::vector&lt;std::unique_ptr&lt;Stmt_WithEnum>> vec;   const auto size = 1'000'000u;      vec.reserve(size);   for (size_t i = 0; i &lt; size; ++i)   {     vec.push_back(factory_2());   }    \/\/ Code inside this loop is measured repeatedly   for (auto _ : state)   {     for (const auto &amp;stmt : vec)     {       if (auto ifStmt =                   Solution1::dyn_cast&lt;const IfStmt_WithEnum *>(stmt.get()))       {         \/\/ Make sure the variable is not optimized away by compiler         benchmark::DoNotOptimize(ifStmt);       }       else if (auto forStmt =                   Solution1::dyn_cast&lt;const ForStmt_WithEnum *>(stmt.get()))       {         \/\/ Make sure the variable is not optimized away by compiler         benchmark::DoNotOptimize(forStmt);       }     }   } } BENCHMARK(StmtWithEnum_Benchmark_1);  static void StmtWithEnum_Benchmark_2(benchmark::State&amp; state)  {   std::vector&lt;std::unique_ptr&lt;Stmt_WithEnum>> vec;   const auto size = 1'000'000u;      vec.reserve(size);   for (size_t i = 0; i &lt; size; ++i)   {     vec.push_back(factory_2());   }    \/\/ Code inside this loop is measured repeatedly   for (auto _ : state)   {     for (const auto &amp;stmt : vec)     {       if (auto ifStmt = Solution2::dyn_cast&lt;                                      const IfStmt_WithEnum *>(stmt.get()))       {         \/\/ Make sure the variable is not optimized away by compiler         benchmark::DoNotOptimize(ifStmt);       }       else if (auto forStmt =                   Solution2::dyn_cast&lt;const ForStmt_WithEnum *>(stmt.get()))       {         \/\/ Make sure the variable is not optimized away by compiler         benchmark::DoNotOptimize(forStmt);       }     }   } } BENCHMARK(StmtWithEnum_Benchmark_2); <\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b12\/1de\/ac3\/b121deac3f969f5d979587e5d37c9bd6.png\" width=\"906\" height=\"803\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b12\/1de\/ac3\/b121deac3f969f5d979587e5d37c9bd6.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0441\u043f\u043e\u0441\u043e\u0431 \u0441 <em>dynamic_cast<\/em> \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u0434\u0432\u0443\u0445 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0442\u043e\u0440\u043e\u043f\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u044b\u0432\u043e\u0434\u0430\u043c\u0438 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0441\u0435\u0431\u044f \u043f\u043e\u0432\u0435\u0434\u0451\u0442 PVS-Studio \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.<\/p>\n<h4>\u0420\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a<\/h4>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441: \u0430 \u0434\u0430\u0451\u0442 \u043b\u0438 \u044d\u0442\u043e \u0445\u043e\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0443? \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439, \u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u0445.<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u0437\u0430\u043c\u0435\u0440\u0430 \u044f \u043f\u043e\u043c\u0435\u043d\u044f\u043b \u043d\u0430\u0448\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0443\u0437\u043b\u0430\u043c\u0438 \u0434\u0435\u0440\u0435\u0432\u0430 \u0438 \u0435\u0451 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u0445. \u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u043d\u0435\u0441\u0443\u0449\u0430\u044f \u0432 \u0441\u0435\u0431\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043c\u0435\u0440\u044b \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0430 <em>SelfTester<\/em> \u2013 \u044d\u0442\u043e \u043d\u0430\u0448\u0430 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0435\u0440\u0451\u0442 \u043f\u0443\u043b \u0438\u0437 123 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0438\u0445 \u0430\u043d\u0430\u043b\u0438\u0437 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 PVS-Studio. \u0423\u0442\u0438\u043b\u0438\u0442\u0430 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0430\u043d\u0430\u043b\u0438\u0437 4-\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432 8 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043b\u043e\u0433 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430. \u042d\u0442\u043e\u0442 \u043b\u043e\u0433 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u043c \u043b\u043e\u0433\u043e\u043c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 \u0445\u043e\u0434\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u043e\u0432 SelfTester \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0436\u0443\u0440\u043d\u0430\u043b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u043e\u0432 \u0432 \u0443\u0434\u043e\u0431\u043d\u043e\u043c \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0432\u0438\u0434\u0435.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 Intel Core i7-9700k;<\/p>\n<\/li>\n<li>\n<p>32 \u0413\u0411 RAM;<\/p>\n<\/li>\n<li>\n<p>Samsung SSD 970 EVO Plus 500GB \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u0438\u0441\u043a\u0430;<\/p>\n<\/li>\n<li>\n<p>WDC WD10EZEX-22MFCA0, \u0442\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f <em>SelfTester<\/em>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0430\u043d\u0430\u043b\u0438\u0437 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0434\u0432\u0430\u0436\u0434\u044b. \u041f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0431\u044b\u043b \u0441 \u044f\u0434\u0440\u043e\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0448 \u0430\u043d\u0430\u043b\u043e\u0433 <em>dyn_cast<\/em> \u0431\u044b\u043b \u0438\u0437\u043c\u0435\u043d\u0451\u043d \u043d\u0430 <em>dynamic_cast<\/em>. \u0412\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u2013 \u0441 \u043d\u0430\u0448\u0438\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c. \u041e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u044f\u0434\u0440\u0430 PVS-Studio.<\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0437\u0430\u043c\u0435\u0440\u043e\u0432 \u043d\u0430 15 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0438\u0437 \u043f\u0443\u043b\u0430:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442<\/p>\n<\/th>\n<th>\n<p>\u0420\u0430\u0437\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, KLOC<\/p>\n<\/th>\n<th>\n<p>\u0412\u0440\u0435\u043c\u044f: dynamic_cast<\/p>\n<\/th>\n<th>\n<p>\u0412\u0440\u0435\u043c\u044f: \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 + static_cast<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">SObjectizer<\/p>\n<\/td>\n<td>\n<p align=\"left\">17.2<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:01:10<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:00:56<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">StrongDC<\/p>\n<\/td>\n<td>\n<p align=\"left\">102<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:00:46<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:00:41<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Notepad++<\/p>\n<\/td>\n<td>\n<p align=\"left\">111<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:02:48<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:02:55<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">WinMerge<\/p>\n<\/td>\n<td>\n<p align=\"left\">172<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:11:02<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:09:48<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">db_10<\/p>\n<\/td>\n<td>\n<p align=\"left\">213<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:36:58<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:32:20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">pcsx2<\/p>\n<\/td>\n<td>\n<p align=\"left\">302<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:04:44<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:04:57<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">dosbox<\/p>\n<\/td>\n<td>\n<p align=\"left\">302<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:05:54<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:04:12<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CamStudio<\/p>\n<\/td>\n<td>\n<p align=\"left\">327<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:09:49<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:08:34<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Shareaza<\/p>\n<\/td>\n<td>\n<p align=\"left\">400<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:40:32<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:36:17<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">mpc-hc<\/p>\n<\/td>\n<td>\n<p align=\"left\">872<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:40:46<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:34:30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">QtParts<\/p>\n<\/td>\n<td>\n<p align=\"left\">1361<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:03:31<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:02:35<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">miranda32<\/p>\n<\/td>\n<td>\n<p align=\"left\">1811<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:32:03<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:27:07<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">awesome-hpp<\/p>\n<\/td>\n<td>\n<p align=\"left\">2196<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:12:01<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:11:37<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">ffdshow<\/p>\n<\/td>\n<td>\n<p align=\"left\">2213<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:36:23<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:34:08<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Freeswitch<\/p>\n<\/td>\n<td>\n<p align=\"left\">3690<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:37:33<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:33:30<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043f\u043e\u0433\u0440\u0435\u0448\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043c \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442<\/p>\n<\/th>\n<th>\n<p>\u0420\u0430\u0437\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, KLOC<\/p>\n<\/th>\n<th>\n<p>\u0412\u0440\u0435\u043c\u044f: dynamic_cast<\/p>\n<\/th>\n<th>\n<p>\u0412\u0440\u0435\u043c\u044f: \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 + static_cast<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">SObjectizer<\/p>\n<\/td>\n<td>\n<p align=\"left\">17.2<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:01:04<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:00:51<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">StrongDC<\/p>\n<\/td>\n<td>\n<p align=\"left\">102<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:00:49<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:00:47<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Notepad++<\/p>\n<\/td>\n<td>\n<p align=\"left\">111<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:03:11<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:02:58<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">WinMerge<\/p>\n<\/td>\n<td>\n<p align=\"left\">172<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:11:23<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:09:44<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">db_10<\/p>\n<\/td>\n<td>\n<p align=\"left\">213<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:37:38<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:32:50<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">pcsx2<\/p>\n<\/td>\n<td>\n<p align=\"left\">302<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:04:49<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:04:35<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">dosbox<\/p>\n<\/td>\n<td>\n<p align=\"left\">302<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:06:05<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:05:20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CamStudio<\/p>\n<\/td>\n<td>\n<p align=\"left\">327<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:10:19<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:09:15<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Shareaza<\/p>\n<\/td>\n<td>\n<p align=\"left\">400<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:40:48<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:36:39<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">mpc-hc<\/p>\n<\/td>\n<td>\n<p align=\"left\">872<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:37:37<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:34:18<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">QtParts<\/p>\n<\/td>\n<td>\n<p align=\"left\">1361<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:03:52<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:03:05<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">miranda32<\/p>\n<\/td>\n<td>\n<p align=\"left\">1811<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:33:04<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:31:28<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">awesome-hpp<\/p>\n<\/td>\n<td>\n<p align=\"left\">2196<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:12:09<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:11:18<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">ffdshow<\/p>\n<\/td>\n<td>\n<p align=\"left\">2213<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:39:32<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:36:04<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Freeswitch<\/p>\n<\/td>\n<td>\n<p align=\"left\">3690<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:36:54<\/p>\n<\/td>\n<td>\n<p align=\"left\">0:32:16<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/87a\/219\/ff8\/87a219ff8e536a018aaec90521075858.png\" width=\"975\" height=\"714\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/87a\/219\/ff8\/87a219ff8e536a018aaec90521075858.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0418\u0437 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u043e\u0432 \u0437\u0430\u043c\u0435\u0442\u043d\u043e, \u0447\u0442\u043e \u0447\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0442\u0435\u043c \u0441\u0438\u043b\u044c\u043d\u0435\u0435 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 <em>dynamic_cast<\/em> \u043d\u0430 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430. \u0410 \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f, \u043f\u0440\u0430\u0432\u043a\u0430 \u043d\u0435 \u0442\u0430\u043a \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0430.<\/p>\n<h3>\u0418\u0442\u043e\u0433\u0438<\/h3>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043e\u0442\u043a\u0430\u0437 \u043e\u0442 RTTI \u043c\u043e\u0436\u0435\u0442 \u0434\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0438\u0433\u0440\u044b\u0448 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u041d\u0435 \u0437\u0440\u044f Clang \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0441 <em>-fno-rtti<\/em>. \u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0441\u043e\u0432\u0441\u0435\u043c \u0443\u0436 \u0437\u0430\u0446\u0438\u043a\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u043c \u0438 \u0432\u043e\u0435\u0432\u0430\u0442\u044c \u0441 RTTI \u0432\u0435\u0437\u0434\u0435, \u0432\u0435\u0434\u044c \u043f\u043e\u0440\u043e\u0439 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u0430\u0436\u043d\u0435\u0435 \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u0430 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u043e\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u0438\u043f\u043e\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439).<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/pvs-studio\/blog\/693014\/\"> https:\/\/habr.com\/ru\/company\/pvs-studio\/blog\/693014\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c \u0421++ \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0432\u0435\u0449\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u043f\u043e\u0434 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0443 &#171;\u041d\u0435 \u043f\u043b\u0430\u0442\u0438 \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0448\u044c&#187;. \u041e\u0434\u043d\u0430 \u0438\u0437 \u043d\u0438\u0445 \u2013 dynamic_cast. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f, \u0447\u0442\u043e \u0441 \u043d\u0438\u043c \u043d\u0435 \u0442\u0430\u043a, \u0430 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0439\u043c\u0451\u043c \u2013 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0443.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u041e\u0431 \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0437\u043e\u0432 \u044f\u0437\u044b\u043a\u0430 C++. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043f\u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0441\u043a\u0443\u0447\u043d\u043e\u0439 \u044d\u0442\u0430 \u0447\u0430\u0441\u0442\u044c, \u0432\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0433\u043b\u0430\u0432\u0435.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<pre><code class=\"cpp\">struct Shape {   virtual void Draw() const = 0; };  struct Circle : Shape {   void Draw() const override; };  struct Triangle : Shape {   void Draw() const override; };  struct Rectangle : Shape {   void Draw() const override; }; <\/code><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435 \u043c\u044b \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c &#171;\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u0435&#187; \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f (<em>upcasting<\/em>) \u0438\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043a \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044e \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"cpp\">#include &lt;memory>  void foo(const Shape *);  void bar() {   std::unique_ptr&lt;Shape>   circle = std::make_unique&lt;Circle>();   std::unique_ptr&lt;Shape> triangle = std::make_unique&lt;Triangle>();   std::unique_ptr&lt;Shape>     rect = std::make_unique&lt;Rectangle>();    foo(circle.get());   foo(triangle.get());   foo(rect.get()); } <\/code><\/pre>\n<p>\u0422.\u043a. \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b <em>Circle<\/em>, <em>Triangle<\/em> \u0438 <em>Rectangle<\/em> \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441 <em>Shape<\/em>, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<p>\u0410 \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0432 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0439? \u041f\u043e\u0434 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c \u043d\u0430 <em>Shape<\/em> \u043c\u043e\u0436\u0435\u0442 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0439 \u043e\u0442 \u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441. \u041d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0436\u0435 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c. \u0422\u0443\u0442 \u043d\u0430 \u0441\u0446\u0435\u043d\u0443 \u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 (<em>runtime type identification<\/em>, \u0441\u043e\u043a\u0440. <em>RTTI<\/em>).<\/p>\n<p>RTTI \u2013 \u044d\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. \u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c RTTI \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u0441\u044f\u043a\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/dynamic_cast\"><em>dynamic_cast<\/em><\/a> \u0438 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/typeid\"><em>typeid<\/em><\/a>. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++ \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f RTTI, \u0438 \u0432\u0441\u044f \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <em>\u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439<\/em> (<em>application binary interface<\/em>, \u0441\u043e\u043a\u0440. <em>ABI<\/em>). \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 (<em>vtable<\/em>). \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b \u0434\u0435\u0442\u0430\u043b\u0438, \u0442\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 <a href=\"https:\/\/itanium-cxx-abi.github.io\/cxx-abi\/abi.html#rtti\">x86_64<\/a>.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 &#171;\u0441\u0443\u0436\u0430\u044e\u0449\u0438\u0435&#187; \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f (<em>downcasting<\/em>) \u0438\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043a \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044e \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c <em>dynamic_cast<\/em>:<\/p>\n<pre><code class=\"cpp\">void Visit(const Shape *ptr) {   if (auto circle = dynamic_cast&lt;const Circle *>(ptr))   {     \/\/ do smth with circle   }   else if (auto triangle = dynamic_cast&lt;const Triangle *>(ptr))   {     \/\/ do smth with triangle   }   else if (auto rect = dynamic_cast&lt;const Rectangle *>(ptr))   {     \/\/ do smth with rect   } } <\/code><\/pre>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, <em>dynamic_cast<\/em> \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u043a\u043e\u0434\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u0442\u0430\u043a \u0447\u0430\u0441\u0442\u043e, <em>typeid<\/em> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0435\u0449\u0435 \u0440\u0435\u0436\u0435. \u041a\u0442\u043e-\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u2013 \u0441\u0438\u043c\u043f\u0442\u043e\u043c \u043f\u043b\u043e\u0445\u043e\u0433\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u0430\u043a \u043e\u0431\u0441\u0442\u043e\u044f\u0442 \u0434\u0435\u043b\u0430 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0430\u043a\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u2013 \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u043d\u0430\u044f \u043c\u0435\u0440\u0430, \u0438 \u0438\u0445 \u0447\u0438\u0441\u043b\u043e \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430\u043c\u0438? \u041d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0438 \u044d\u0442\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u2013 \u0441\u043b\u0430\u0437\u0438\u0442\u044c \u0432 <em>vtable<\/em>? \u041e\u0431 \u044d\u0442\u043e\u043c \u043c\u044b \u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c.<\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u043a\u0430<\/h3>\n<p>\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u044b, \u043a\u0430\u043a \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0435\u0433\u043e \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u043e \u0438\u0437 \u043d\u0438\u0445 \u2013 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e (AST). \u0412 \u043d\u0451\u043c \u0443\u0437\u043b\u044b \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0432 \u0440\u043e\u043b\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439.<\/p>\n<p>\u0423\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c AST \u0432 \u043a\u043e\u0434\u0435 \u2013 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 Clang \u0443\u0437\u043b\u044b \u0434\u0435\u0440\u0435\u0432\u0430 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442\u0441\u044f \u043e\u0442 \u0442\u0430\u043a\u0438\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043a\u0430\u043a <a href=\"https:\/\/clang.llvm.org\/doxygen\/classclang_1_1Decl.html\"><em>Decl<\/em><\/a> (\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438 \u0442\u0438\u043f\u043e\u0432) \u0438 <a href=\"https:\/\/clang.llvm.org\/doxygen\/classclang_1_1Stmt.html\"><em>Stmt<\/em><\/a> (\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439).<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"cpp\">{   for (size_t i = 0; i &lt; 10; ++i) ;   if (true) ; } <\/code><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430\u043c \u044f\u0437\u044b\u043a\u043e\u0432 <a href=\"https:\/\/en.cppreference.com\/w\/c\/language\/statements\">C<\/a> \u0438 <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/statements\">C++<\/a>, \u044d\u0442\u043e \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f (\u0431\u043b\u043e\u043a), \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0446\u0438\u043a\u043b <em>for<\/em> \u0438 \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 <em>if<\/em>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435, \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"cpp\">\/\/ Base class for all type of statements struct Stmt { \/* .... *\/ };  \/\/ Base class for all type of expressions struct Expr { \/* .... *\/ };  \/\/ Base class for all types of declarations struct Decl { \/* .... *\/ };  struct IfStmt : Stmt {   const Expr&amp; GetCondition() const noexcept;   const Stmt&amp; GetBody()      const noexcept;   const Stmt* GetElse()      const noexcept;    \/\/ .... };  struct ForStmt : Stmt {   const Decl* GetInit()         const noexcept;   const Expr* GetCondition()    const noexcept;   const Expr* GetPostBodyExpr() const noexcept;   const Stmt&amp; GetBody()         const noexcept;    \/\/ .... };  using StatementList = ....;  struct CompoundStmt : Stmt {   auto begin() const noexcept { return stmts.begin(); }   auto end() const noexcept { return stmts.end(); }    private:   StatementList stmts;    \/\/ .... }; <\/code><\/pre>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u043a\u043b\u0430\u0441\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <em>std::vector<\/em>. \u0422\u0430\u043a \u043a\u0430\u043a \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0432 \u044f\u0437\u044b\u043a\u0430\u0445 \u043d\u0438 \u043e\u0434\u043d\u0430 \u0438 \u0434\u0430\u0436\u0435 \u043d\u0435 \u0434\u0432\u0435, \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <em>Stmt<\/em>. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"cpp\">void foo(const CompoundStmt *compStmt) {   for (auto stmt : compStmt)   {     \/\/ do smth   } } <\/code><\/pre>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u0441\u0432\u043e\u044e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443:<\/p>\n<pre><code class=\"cpp\">void Visit(const IfStmt &amp;); void Visit(const ForStmt &amp;); <\/code><\/pre>\n<p>\u0418 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u2013 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043a\u0430\u043a\u0430\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u043f\u043e\u0434 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c \u043d\u0430 <em>Stmt<\/em> \u0438 \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0443:<\/p>\n<pre><code class=\"cpp\">void foo(const Stmt *stmt) {   for (auto stmt : compStmt)   {     if (auto ifStmt = dynamic_cast&lt;const IfStmt *>(stmt))     {       Visit(*ifStmt);     }     else if (auto forStmt = dynamic_cast&lt;const ForStmt *>(stmt))     {       Visit(*forStmt);     }   } } <\/code><\/pre>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u0442\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0430\u044f \u0434\u0435\u0442\u0430\u043b\u044c, \u0438\u0437-\u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043a\u043e\u0434 \u0432\u044b\u0448\u0435 <strong>\u043c\u043e\u0436\u0435\u0442<\/strong> \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f. \u0415\u0441\u043b\u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <em>Stmt<\/em> \u043d\u0435 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0435\u043d, \u0442\u043e \u043c\u0430\u0433\u0438\u044f <em>dynamic_cast<\/em> \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">struct Stmt { virtual void Dummy(); \/* .... *\/ }; <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432. \u041f\u043e\u043a\u0430 \u043d\u0435 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d RTTI. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430\u0445 GCC\/Clang \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0444\u043b\u0430\u0433 <em>-fno-rtti<\/em> (GCC, Clang), \u0432 MSVC \u2013 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c <em>\/GR-<\/em>. \u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 RTTI \u043d\u0435 \u0437\u0430\u0434\u0435\u0432\u0430\u0435\u0442 <a href=\"https:\/\/godbolt.org\/z\/zcso7rTcz\">\u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439<\/a> \u0438 <a href=\"https:\/\/godbolt.org\/z\/KeEM88vP9\">\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e<\/a>.<\/p>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u043f\u043e\u043a\u0430 \u0433\u043e\u0442\u043e\u0432\u0438\u043b \u0441\u0442\u0430\u0442\u044c\u044e, \u043d\u0430\u0448\u0451\u043b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043e\u043f\u0440\u043e\u0441 \u043d\u0430 <a href=\"https:\/\/isocpp.org\/files\/papers\/CppDevSurvey-2019-04-summary.pdf\">isocpp.org<\/a>. \u0412 \u043d\u0451\u043c \u0438\u0437 <em>2058<\/em> \u0440\u0435\u0441\u043f\u043e\u043d\u0434\u0435\u043d\u0442\u043e\u0432 <em>14%<\/em> \u043e\u0442\u0432\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u043e\u043d\u0438 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u044e\u0442 RTTI \u043d\u0430 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u0445, \u0430 <em>18%<\/em> \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0435\u0433\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<p>\u041f\u043e\u0434\u044b\u0442\u043e\u0436\u0438\u043c, <em>dynamic_cast<\/em> \u043f\u043b\u043e\u0445 \u0442\u0435\u043c, \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u044b\u0445 \u0442\u0438\u043f\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0444\u043b\u0430\u0433\u043e\u043c <em>-fno-rtti<\/em>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f ABI-\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u0438\u043f\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>&#171;\u0421\u0443\u0436\u0430\u044e\u0449\u0438\u0435&#187; \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 <em>vtable,<\/em> \u0430 \u044d\u0442\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f &#171;<a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9F%D0%BE%D1%81%D0%B5%D1%82%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)\">\u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044c<\/a>&#187; (\u0432\u0438\u0437\u0438\u0442\u043e\u0440). \u041e\u043d\u043e \u0438\u0437\u0431\u0430\u0432\u0438\u0442 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c <em>dynamic_cast<\/em> \u0446\u0435\u043d\u043e\u0439 \u043e\u0434\u043d\u043e\u0433\u043e-\u0434\u0432\u0443\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0438\u043d\u0430\u0447\u0435.<\/p>\n<h3>\u041f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439 dynamic_cast<\/h3>\n<h4>\u042d\u0442\u043e \u0431\u0430\u0437\u0430<\/h4>\n<p>\u0420\u0435\u0446\u0435\u043f\u0442 \u043b\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043f\u0440\u043e\u0441\u0442. \u041c\u044b \u0432\u043d\u0435\u0434\u0440\u0438\u043c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u0435 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u0442\u0438\u043f\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u0441\u0430\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0435\u0451. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">struct Stmt {    enum Type { IfStmt, ForStmt, DoStmt, WhileStmt, ....  };   const Type m_kind;   Stmt(Type kind) : m_kind { kind } { \/* .... *\/ }   \/* .... *\/ };  struct IfStmt : Stmt {   IfStmt() : Stmt { Stmt::Type::IfStmt } { \/* .... *\/ }   \/* .... *\/ };  struct ForStmt : Stmt {   ForStmt() : Stmt { Stmt::Type::ForStmt } { \/* .... *\/ }   \/* .... *\/ }; <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u044b \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0442\u0438\u043f \u0432 \u043f\u043e\u043b\u0435 <em>m_kind<\/em>. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u0438\u043f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cpp\">void foo(const Stmt *stmt) {   if (stmt->m_kind == Stmt::Type::IfStmt)   {     auto ifStmt = static_cast&lt;const IfStmt *>(stmt)     Visit(*ifStmt);   }   else if (stmt->m_kind == Stmt::Type::ForStmt)   {     auto forStmt = static_cast&lt;const ForStmt *>(stmt)     Visit(*forStmt);   } } <\/code><\/pre>\n<p>\u0418\u0437 \u043f\u043b\u044e\u0441\u043e\u0432 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u043e\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0435\u0437 RTTI.<\/p>\n<\/li>\n<li>\n<p>\u041c\u044b \u0441\u0430\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u0438\u043f\u0435. \u0423 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u2013 \u044d\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0411\u044b\u0441\u0442\u0440\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <em>static_cast<\/em> \u0432 \u0442\u0435\u043e\u0440\u0438\u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <em>dynamic_cast<\/em>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e, \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0438 \u043c\u0438\u043d\u0443\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u041c\u044b \u043f\u0438\u0448\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p><em>static_cast<\/em> \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <a href=\"https:\/\/godbolt.org\/z\/Kb175eh4E\">\u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c<\/a> \u0438 \u043a\u043e\u0434 \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041d\u043e \u043c\u043d\u043e\u0433\u043e \u043b\u0438 \u043b\u044e\u0434\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 2022 \u0433\u043e\u0434\u0443?<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u043d\u0430 \u043a\u043e\u0434, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c &#171;\u0410 \u0433\u0434\u0435 \u0437\u0434\u0435\u0441\u044c \u0430\u043d\u0430\u043b\u043e\u0433 <em>dynamic_cast<\/em>&#171;? \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e. \u0427\u0442\u043e\u0431 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0439. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0443 \u043d\u0430\u0441 \u0432 PVS-Studio \u0438 \u0432 LLVM.<\/p>\n<h4>\u041d\u0430\u0432\u043e\u0434\u0438\u043c \u043a\u0440\u0430\u0441\u043e\u0442\u0443. \u041f\u043e\u0434\u0445\u043e\u0434 \u0432 PVS-Studio<\/h4>\n<p>\u0412\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043c\u0435\u0440\u0443:<\/p>\n<pre><code class=\"cpp\">struct Stmt {    enum Type { IfStmt, ForStmt, DoStmt, WhileStmt, ....  };   Stmt(Type kind) : m_kind { kind } { \/* .... *\/ }   Type Kind() const { return m_kind; } private:   const Type m_kind;   \/* .... *\/ }; <\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <em>IsA<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0448 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f. \u0412\u043d\u0443\u0442\u0440\u0438 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0438 \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0439 <em>kind<\/em>.<\/p>\n<pre><code class=\"cpp\">template &lt;typename T, typename Kind> bool IsA(T *p, Kind kind) noexcept {   return p &amp;&amp; p->Kind() == kind; } <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0430\u0440\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0431\u0435\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"cpp\">template &lt;Stmt::Type K> struct type_from_kind;  template &lt;typename T> struct kind_from_type; <\/code><\/pre>\n<p>\u041e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0441\u0432\u044f\u0436\u0435\u043c \u0442\u0438\u043f \u0443\u0437\u043b\u0430 \u0434\u0435\u0440\u0435\u0432\u0430 \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0443\u044e\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<pre><code class=\"cpp\">template &lt;> struct type_from_kind&lt;Stmt::IfStmt> {   using type = IfStmt; };  template &lt;> struct kind_from_type&lt;IfStmt> {   static constexpr auto value =<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-339627","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/339627","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=339627"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/339627\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=339627"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=339627"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=339627"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}