⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtti.html

📁 关于 C++ 的历史无须我来介绍了
💻 HTML
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>



  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">



  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">



  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">



  
  
  
  <title>执行时期型态资讯(RTTI)</title>
</head>


<body>



<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>



<h1><a href="CppGossip.html">C++
Gossip: 执行时期型态资讯(RTTI)</a></h1>



在C++这种可以进行多型机制的语言中,您可以将基底类别指标指向衍生类别物件,这种指定通常在执行时期后发生,您并无法在编译时期即得知指标所指向的物件型态,而必须在执行时期取得物件的执行时期资讯。<br>


<br>


RTTI 全名为Run-Time Type Information,也有人作Run-Time Type
Identification,C++中用来取得指标或参考所实际代表的物件,您可以使用typeid()来取得物件于执行时期的资讯,要使用
typeid(),您必须包括&lt;typeinfo&gt;标头档,typeid()使用时传入一个物件: <br>


<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">typeid(object);</span><br>


</div>



<br>


typeid()会传回一个type_info物件,其拥有几个成员可以描述或进行物件的比较:<br>


<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">const char *name(); // 取得物件型态名称 </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">


<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">bool before(const type_info &amp;ob);&nbsp; // 当物件的名称顺序位于ob之前时,传回true </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">


<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">bool operator==(const type_info &amp;ob);&nbsp; // 比较物件型态是否相同 </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">


<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">bool operator!=(const type_info &amp;ob); // 比较物件型态是否不同</span><br>


</div>


<br>


==与!=运算子在这边被重载为可以比较两个物件的型态是否相同;typeid()也可以使用型态名称作为引数,这通常是用来取得一个type-info物件,并与一个物件作比较时使用: 
<br>


<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">typeid(type-name);</span><br>


</div>


<br>


用范例来说明typeid()与其成员的使用方法与应用,下面这个程式只是使用name()取得物件的型态名称: <br>


<br>



<pre>#include &lt;iostream&gt; <br>#include &lt;typeinfo&gt; <br>using namespace std; <br><br>class Base { <br>public: <br>    virtual void foo() { <br>        cout &lt;&lt; "Base" &lt;&lt; endl; <br>    } <br>}; <br><br>class Derived1 : public Base { <br>public: <br>    void foo() { <br>        cout &lt;&lt; "Derived1" &lt;&lt; endl; <br>    } <br>}; <br><br>class Derived2 : public Base { <br>public: <br>    void foo() { <br>        cout &lt;&lt; "Derived2" &lt;&lt; endl; <br>    } <br>}; <br><br>int main() { <br>    Base *ptr;  // 基底类别指标 <br>    Base base; <br>    Derived1 derived1;<br>    Derived2 derived2; <br><br>    ptr = &amp;base;<br>    cout &lt;&lt; "ptr 指向 " <br>         &lt;&lt; typeid(*ptr).name()  <br>         &lt;&lt; endl; <br><br>    ptr = &amp;derived1; <br>    cout &lt;&lt; "ptr 指向 " <br>         &lt;&lt; typeid(*ptr).name() <br>         &lt;&lt; endl; <br><br>    ptr = &amp;derived2; <br>    cout &lt;&lt; "ptr 指向 " <br>         &lt;&lt; typeid(*ptr).name() <br>         &lt;&lt; endl;<br>    <br>    return 0;<br>}</pre>




<span class="postbody"><br>


执行结果:</span><br>



<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">



  <tbody>



    <tr>



      <td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">ptr 指向 4Base<br>


ptr 指向 8Derived1<br>


ptr 指向 8Derived2</span></small><span style="color: rgb(255, 255, 255);"><br>



      </span></td>



    </tr>



  
  
  
  </tbody>
</table>



<br>


您使用共同的基底类别指标来指向基底类别物件与衍生类别物件,虽然如此,还是利用typeid()取回的type-info物件仍可以得知物件的型态名称。 <br>


<br>


RTTI的使用时机之一,就是当您将物件以参考方式传递给函式时,函式的参数使用共同的基底类别指标或参考,但在函式中有必须操作衍生类别中的某个方法,由于函式事先并不知道您传入的物件型态名称,所以您必须利用RTTI来进行判断,下面的程式是个简单的例子: <br>


<br>



<pre>#include &lt;iostream&gt; <br>#include &lt;typeinfo&gt; <br>using namespace std; <br><br>class Base { <br>public: <br>    virtual void foo() = 0;<br>}; <br><br>class Derived1 : public Base { <br>public: <br>    void foo() { <br>        cout &lt;&lt; "Derived1" &lt;&lt; endl; <br>    } <br>    <br>    void showOne() {<br>         cout &lt;&lt; "Yes! It's Derived1." &lt;&lt; endl;<br>    }<br>}; <br><br>class Derived2 : public Base { <br>public: <br>    void foo() { <br>        cout &lt;&lt; "Derived2" &lt;&lt; endl; <br>    } <br>    <br>    void showTwo() {<br>         cout &lt;&lt; "Yes! It's Derived2." &lt;&lt; endl;<br>    }<br>}; <br><br>void showWho(Base *base) {<br>    base-&gt;foo();<br>     <br>    if(typeid(*base) == typeid(Derived1)) {<br>        Derived1 *derived1 = static_cast&lt;Derived1*&gt;(base);<br>        derived1-&gt;showOne();<br>    }<br>    else if(typeid(*base) == typeid(Derived2)) {<br>        Derived2 *derived2 = static_cast&lt;Derived2*&gt;(base);<br>        derived2-&gt;showTwo();    <br>    } <br>}<br><br>int main() { <br>    Derived1 derived1;<br>    Derived2 derived2; <br><br>    showWho(&amp;derived1);<br>    showWho(&amp;derived2);<br>    <br>    return 0;<br>}</pre>


<br>


<span class="postbody">执行结果:</span><br>



<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">



  <tbody>



    <tr>



      <td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">Derived1<br>


Yes! It's Derived1.<br>


Derived2<br>


Yes! It's Derived2.</span></small><span style="color: rgb(255, 255, 255);"><br>



      </span></td>



    </tr>



  
  
  
  </tbody>
</table>


<br>


传统的C风格转型语法也是可以使用的,例如:<br>


<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">Derived1 *derived1 = (Derived1*) base;</span><br>


</div>


<br>


当然不建议使用这种方式强制转型,事实上使用static_cast也不是很适合,C++为了支援RTTI还提供有dynamic_cast,这在下一个主题中介绍。<br>


<br>


<br>



</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -