📄 chap09.htm
字号:
<font color=#009900>// Counting shapes</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include <font color=#004488>"..</font><font color=#004488>/purge.h"</font>
#include <iostream>
#include <ctime>
#include <typeinfo>
#include <vector>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#0000ff>class</font> Shape {
<font color=#0000ff>protected</font>:
<font color=#0000ff>static</font> <font color=#0000ff>int</font> count;
<font color=#0000ff>public</font>:
Shape() { count++; }
<font color=#0000ff>virtual</font> ~Shape() { count--; }
<font color=#0000ff>virtual</font> <font color=#0000ff>void</font> draw() <font color=#0000ff>const</font> = 0;
<font color=#0000ff>static</font> <font color=#0000ff>int</font> quantity() { <font color=#0000ff>return</font> count; }
};
<font color=#0000ff>int</font> Shape::count = 0;
<font color=#0000ff>class</font> SRectangle : <font color=#0000ff>public</font> Shape {
<font color=#0000ff>void</font> <font color=#0000ff>operator</font>=(SRectangle&); <font color=#009900>// Disallow</font>
<font color=#0000ff>protected</font>:
<font color=#0000ff>static</font> <font color=#0000ff>int</font> count;
<font color=#0000ff>public</font>:
SRectangle() { count++; }
SRectangle(<font color=#0000ff>const</font> SRectangle&) { count++;}
~SRectangle() { count--; }
<font color=#0000ff>void</font> draw() <font color=#0000ff>const</font> {
cout << <font color=#004488>"SRectangle::draw()"</font> << endl;
}
<font color=#0000ff>static</font> <font color=#0000ff>int</font> quantity() { <font color=#0000ff>return</font> count; }
};
<font color=#0000ff>int</font> SRectangle::count = 0;
<font color=#0000ff>class</font> SEllipse : <font color=#0000ff>public</font> Shape {
<font color=#0000ff>void</font> <font color=#0000ff>operator</font>=(SEllipse&); <font color=#009900>// Disallow</font>
<font color=#0000ff>protected</font>:
<font color=#0000ff>static</font> <font color=#0000ff>int</font> count;
<font color=#0000ff>public</font>:
SEllipse() { count++; }
SEllipse(<font color=#0000ff>const</font> SEllipse&) { count++; }
~SEllipse() { count--; }
<font color=#0000ff>void</font> draw() <font color=#0000ff>const</font> {
cout << <font color=#004488>"SEllipse::draw()"</font> << endl;
}
<font color=#0000ff>static</font> <font color=#0000ff>int</font> quantity() { <font color=#0000ff>return</font> count; }
};
<font color=#0000ff>int</font> SEllipse::count = 0;
<font color=#0000ff>class</font> SCircle : <font color=#0000ff>public</font> SEllipse {
<font color=#0000ff>void</font> <font color=#0000ff>operator</font>=(SCircle&); <font color=#009900>// Disallow</font>
<font color=#0000ff>protected</font>:
<font color=#0000ff>static</font> <font color=#0000ff>int</font> count;
<font color=#0000ff>public</font>:
SCircle() { count++; }
SCircle(<font color=#0000ff>const</font> SCircle&) { count++; }
~SCircle() { count--; }
<font color=#0000ff>void</font> draw() <font color=#0000ff>const</font> {
cout << <font color=#004488>"SCircle::draw()"</font> << endl;
}
<font color=#0000ff>static</font> <font color=#0000ff>int</font> quantity() { <font color=#0000ff>return</font> count; }
};
<font color=#0000ff>int</font> SCircle::count = 0;
<font color=#0000ff>int</font> main() {
vector<Shape*> shapes;
srand(time(0)); <font color=#009900>// Seed random number generator</font>
<font color=#0000ff>const</font> <font color=#0000ff>int</font> mod = 12;
<font color=#009900>// Create a random quantity of each type:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < rand() % mod; i++)
shapes.push_back(<font color=#0000ff>new</font> SRectangle);
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> j = 0; j < rand() % mod; j++)
shapes.push_back(<font color=#0000ff>new</font> SEllipse);
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> k = 0; k < rand() % mod; k++)
shapes.push_back(<font color=#0000ff>new</font> SCircle);
<font color=#0000ff>int</font> nCircles = 0;
<font color=#0000ff>int</font> nEllipses = 0;
<font color=#0000ff>int</font> nRects = 0;
<font color=#0000ff>int</font> nShapes = 0;
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> u = 0; u < shapes.size(); u++) {
shapes[u]->draw();
<font color=#0000ff>if</font>(<font color=#0000ff>dynamic_cast</font><SCircle*>(shapes[u]))
nCircles++;
<font color=#0000ff>if</font>(<font color=#0000ff>dynamic_cast</font><SEllipse*>(shapes[u]))
nEllipses++;
<font color=#0000ff>if</font>(<font color=#0000ff>dynamic_cast</font><SRectangle*>(shapes[u]))
nRects++;
<font color=#0000ff>if</font>(<font color=#0000ff>dynamic_cast</font><Shape*>(shapes[u]))
nShapes++;
}
cout << endl << endl
<< <font color=#004488>"Circles = "</font> << nCircles << endl
<< <font color=#004488>"Ellipses = "</font> << nEllipses << endl
<< <font color=#004488>"Rectangles = "</font> << nRects << endl
<< <font color=#004488>"Shapes = "</font> << nShapes << endl
<< endl
<< <font color=#004488>"SCircle::quantity() = "</font>
<< SCircle::quantity() << endl
<< <font color=#004488>"SEllipse::quantity() = "</font>
<< SEllipse::quantity() << endl
<< <font color=#004488>"SRectangle::quantity() = "</font>
<< SRectangle::quantity() << endl
<< <font color=#004488>"Shape::quantity() = "</font>
<< Shape::quantity() << endl;
purge(shapes);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Both types work for this example, but the
<B>static</B> member approach can be used only if you own the code and have
installed the <B>static</B> members and functions (or if a vendor provides them
for you). In addition, the syntax for RTTI may then be different from one class
to
another.</FONT><A NAME="_Toc312374136"></A><A NAME="_Toc519042084"></A><BR></P></DIV>
<A NAME="Heading291"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Syntax specifics</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This section looks at the details of how
the two forms of RTTI work, and how they
differ.</FONT><A NAME="_Toc312374137"></A><A NAME="_Toc519042085"></A><BR></P></DIV>
<A NAME="Heading292"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
typeid( ) with built-in types</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">For consistency, the
<B>typeid( )<A NAME="Index530"></A><A NAME="Index531"></A><A NAME="Index532"></A></B>
operator works with built-in types. So the following expressions are
true:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C09:TypeidAndBuiltins.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include <cassert>
#include <typeinfo>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#0000ff>int</font> main() {
assert(<font color=#0000ff>typeid</font>(47) == <font color=#0000ff>typeid</font>(<font color=#0000ff>int</font>));
assert(<font color=#0000ff>typeid</font>(0) == <font color=#0000ff>typeid</font>(<font color=#0000ff>int</font>));
<font color=#0000ff>int</font> i;
assert(<font color=#0000ff>typeid</font>(i) == <font color=#0000ff>typeid</font>(<font color=#0000ff>int</font>));
assert(<font color=#0000ff>typeid</font>(&i) == <font color=#0000ff>typeid</font>(<font color=#0000ff>int</font>*));
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><A NAME="_Toc312374138"></A><A NAME="_Toc519042086"></A><BR></P></DIV>
<A NAME="Heading293"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Producing the proper type name</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>typeid( )</B> must work properly
in all situations. For example, the following class contains a nested
class<A NAME="Index533"></A><A NAME="Index534"></A>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C09:RTTIandNesting.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include <iostream>
#include <typeinfo>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#0000ff>class</font> One {
<font color=#0000ff>class</font> Nested {};
Nested* n;
<font color=#0000ff>public</font>:
One() : n(<font color=#0000ff>new</font> Nested) {}
~One() { <font color=#0000ff>delete</font> n; }
Nested* nested() { <font color=#0000ff>return</font> n; }
};
<font color=#0000ff>int</font> main() {
One o;
cout << <font color=#0000ff>typeid</font>(*o.nested()).name() << endl;
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>typeinfo::name( )</B> member
function will still produce the proper class name; the result is
<B>One::Nested</B>.</FONT><A NAME="_Toc312374139"></A><A NAME="_Toc519042087"></A><BR></P></DIV>
<A NAME="Heading294"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Nonpolymorphic
types<BR><A NAME="Index535"></A><A NAME="Index536"></A><A NAME="Index537"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Although <B>typeid( )</B> works with
nonpolymorphic types (those that don’t have a virtual function in the base
class), the information you get this way is dubious. For the following class
hierarchy,</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C09:RTTIWithoutPolymorphism.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include <cassert>
#include <typeinfo>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#0000ff>class</font> X {
<font color=#0000ff>int</font> i;
<font color=#0000ff>public</font>:
<font color=#009900>// ...</font>
};
<font color=#0000ff>class</font> Y : <font color=#0000ff>public</font> X {
<font color=#0000ff>int</font> j;
<font color=#0000ff>public</font>:
<font color=#009900>// ...</font>
};
<font color=#0000ff>int</font> main() {
X* xp = <font color=#0000ff>new</font> Y;
assert(<font color=#0000ff>typeid</font>(*xp) == <font color=#0000ff>typeid</font>(X));
assert(<font color=#0000ff>typeid</font>(*xp) != <font color=#0000ff>typeid</font>(Y));
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you create an object of the derived
type and upcast it,</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>X* xp = <font color=#0000ff>new</font> Y;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>typeid( )</B> operator will
produce results, but not the ones you might expect. Because there’s no
polymorphism, the static type information is used:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>typeid</font>(*xp) == <font color=#0000ff>typeid</font>(X)
<font color=#0000ff>typeid</font>(*xp) != <font color=#0000ff>typeid</font>(Y)</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">RTTI is intended for use only with
polymorphic
classes.</FONT><A NAME="_Toc312374140"></A><A NAME="_Toc519042088"></A><BR></P></DIV>
<A NAME="Heading295"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Casting to intermediate
levels<BR><A NAME="Index538"></A><A NAME="Index539"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>dynamic_cast</B> can detect both exact
types and, in an inheritance hierarchy with multiple levels, intermediate types.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -