📄 dynamiccast.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>使用 dynamic_cast</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: 使用 dynamic_cast</a></h1>
您可以使用static_cast(甚至是传统的C转型方式)将基底类别指标转换为衍生类别指标,这种转型方式是强制转型,在执行时期使用强制转型有危险性,因为编译器无法得知转型是否正确,执行时期真正指向的物件型态是未知的,透过简单的检查是避免错误的一种方式:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">if(typeid(*base) == typeid(Derived1)) {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> Derived1 *derived1 = static_cast<Derived1*>(base);</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> derived1->showOne();</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">}</span><br>
</div>
<br>
为了支援执行时期的型态转换动作,C++提供了dynamic_cast用来将一个基底类别的指标转型至衍生类别指标,称之为“安全向下转型”(Safe downcasting),它在执行时期进行型态转换动作,首先会确定转换目标与来源是否属同一个类别阶
层,接着才真正进行转换的动作,检验动作在执行时期完成,如果是一个指标,则转换成功时传回位址,失败的话会传回0,如果是参考的话,转换失败会丢出
bad_cast例外。<br>
<br>
可以将 <a href="RTTI.html">执行时期型态资讯(RTTI)</a> 中的showWho()函式如下修改:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">void showWho(Base *base) {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> base->foo();</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> if(Derived1 *derived1 = dynamic_cast<Derived1*>(base)) {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> derived1->showOne();</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> }</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> else if(Derived2 *derived2 = static_cast<Derived2*>(base)) {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> derived2->showTwo(); </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> } </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">}</span><br>
</div>
<br>
由于dynamic_cast转换失败的话会传回0,因而运算的结果不可使用,必须先行对转换结果作检查才可以,如上例所示。<br>
<br>
如果使用参考的话,dynamic_cast在转换失败之后会丢出bad_cast例外,所以您必须使用try...catch来处理例外,例如:<br>
<br>
<pre>#include <iostream> <br>#include <typeinfo> <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 << "Derived1" << endl; <br> } <br> <br> void showOne() {<br> cout << "Yes! It's Derived1." << endl;<br> }<br>}; <br><br>class Derived2 : public Base { <br>public: <br> void foo() { <br> cout << "Derived2" << endl; <br> } <br> <br> void showTwo() {<br> cout << "Yes! It's Derived2." << endl;<br> }<br>}; <br><br>void showWho(Base &base) {<br> try {<br> Derived1 derived1 = dynamic_cast<Derived1&>(base);<br> derived1.showOne();<br> }<br> catch(bad_cast) {<br> cout << "bad_cast 转型失败" << endl;<br> }<br><br>}<br><br>int main() { <br> Derived1 derived1;<br> Derived2 derived2; <br><br> showWho(derived1);<br> showWho(derived2);<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);">Yes! It's Derived1.<br>
bad_cast 转型失败</span></small><span style="color: rgb(255, 255, 255);"><br>
</span></td>
</tr>
</tbody>
</table>
<br>
<br>
<br>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -