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

📄 chap11.htm

📁 This is the second part of that lab manual to teach you how to make real-time programme and how to d
💻 HTM
📖 第 1 页 / 共 5 页
字号:

<font color=#0000ff>class</font> Kitty: <font color=#0000ff>public</font> Player {
  <font color=#0000ff>virtual</font> <font color=#0000ff>void</font> interactWith(Obstacle* ob) {
    cout &lt;&lt; <font color=#004488>"Kitty has encountered a "</font>;
    ob-&gt;action();
  }
};

<font color=#0000ff>class</font> KungFuGuy: <font color=#0000ff>public</font> Player {
  <font color=#0000ff>virtual</font> <font color=#0000ff>void</font> interactWith(Obstacle* ob) {
    cout &lt;&lt; <font color=#004488>"KungFuGuy now battles against a "</font>;
    ob-&gt;action();
  }
};

<font color=#0000ff>class</font> Puzzle: <font color=#0000ff>public</font> Obstacle {
<font color=#0000ff>public</font>:
  <font color=#0000ff>void</font> action() { cout &lt;&lt; <font color=#004488>"Puzzle\n"</font>; }
};

<font color=#0000ff>class</font> NastyWeapon: <font color=#0000ff>public</font> Obstacle {
<font color=#0000ff>public</font>:
  <font color=#0000ff>void</font> action() { cout &lt;&lt; <font color=#004488>"NastyWeapon\n"</font>; }
};

<font color=#009900>// The abstract factory:</font>
<font color=#0000ff>class</font> GameElementFactory {
<font color=#0000ff>public</font>:
  <font color=#0000ff>virtual</font> Player* makePlayer() = 0;
  <font color=#0000ff>virtual</font> Obstacle* makeObstacle() = 0;
};

<font color=#009900>// Concrete factories:</font>
<font color=#0000ff>class</font> KittiesAndPuzzles : 
  <font color=#0000ff>public</font> GameElementFactory {
<font color=#0000ff>public</font>:
  <font color=#0000ff>virtual</font> Player* makePlayer() { 
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> Kitty;
  }
  <font color=#0000ff>virtual</font> Obstacle* makeObstacle() {
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> Puzzle;
  }
};

<font color=#0000ff>class</font> KillAndDismember : 
  <font color=#0000ff>public</font> GameElementFactory {
<font color=#0000ff>public</font>:
  <font color=#0000ff>virtual</font> Player* makePlayer() { 
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> KungFuGuy;
  }
  <font color=#0000ff>virtual</font> Obstacle* makeObstacle() {
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> NastyWeapon;
  }
};

<font color=#0000ff>class</font> GameEnvironment {
  GameElementFactory* gef;
  Player* p;
  Obstacle* ob;
<font color=#0000ff>public</font>:
  GameEnvironment(GameElementFactory* factory) :
    gef(factory), p(factory-&gt;makePlayer()), 
    ob(factory-&gt;makeObstacle()) {}
  <font color=#0000ff>void</font> play() {
    p-&gt;interactWith(ob);
  }
  ~GameEnvironment() {
    <font color=#0000ff>delete</font> p;
    <font color=#0000ff>delete</font> ob;
    <font color=#0000ff>delete</font> gef;
  }
};

<font color=#0000ff>int</font> main() {
  GameEnvironment 
    g1(<font color=#0000ff>new</font> KittiesAndPuzzles),
    g2(<font color=#0000ff>new</font> KillAndDismember);
  g1.play();
  g2.play();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In this environment, <B>Player</B>
objects interact with <B>Obstacle</B> objects, but there are different types of
players and obstacles depending on what kind of game you&#8217;re playing. You
determine the kind of game by choosing a particular <B>GameElementFactory</B>,
and then the <B>GameEnvironment</B> controls the setup and play of the game. In
this example, the setup and play is very simple, but those activities (the
<I>initial conditions</I> and the <I>state change</I>) can determine much of the
game&#8217;s outcome. Here, <B>GameEnvironment</B> is not designed to be
inherited, although it could very possibly make sense to do
that.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This also contains examples of <I>Double
Dispatching</I> and the <I>Factory Method</I>, both of which will be explained
later.</FONT><A NAME="_Toc519042126"></A><BR></P></DIV>
<A NAME="Heading336"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Virtual constructors</H3></FONT>
<DIV ALIGN="LEFT"><P><BR>Show simpler version of virtual constructor scheme,
letting the user create the object with new. Probably make constructor for
objects private and use a maker function to force all objects on the
heap.<BR></P></DIV>
<FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One of the primary goals of using a
factory is so that
<A NAME="Index663"></A><A NAME="Index664"></A><A NAME="Index665"></A>you can
organize your code so you don&#8217;t have to select an exact type of
constructor when creating an object. That is, you can say, &#8220;I don&#8217;t
know precisely what type of object you are, but here&#8217;s the information:
Create yourself.&#8221; </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In addition, during a constructor call
the virtual mechanism does not operate (early binding occurs). Sometimes this is
awkward. For example, in the <B>Shape </B>program it seems logical that inside
the constructor for a <B>Shape</B> object, you would want to set everything up
and then <B>draw(&#160;)</B> the <B>Shape</B>. <B>draw(&#160;)</B> should be a
virtual function, a message to the <B>Shape</B> that it should draw itself
appropriately, depending on whether it is a circle, square, line, and so on.
However, this doesn&#8217;t work inside the constructor, for the reasons given
in Chapter XX: Virtual functions<A NAME="Index666"></A><A NAME="Index667"></A>
resolve to the &#8220;local&#8221; function bodies when called in
constructors.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you want to be able to call a virtual
function inside the constructor and have it do the right thing, you must use a
technique to <I>simulate</I> a virtual constructor (which is a variation of the
<I>Factory Method</I>). This is a conundrum. Remember the idea of a virtual
function is that you send a message to an object and let the object figure out
the right thing to do. But a constructor builds an object. So a virtual
constructor would be like saying, &#8220;I don&#8217;t know exactly what type of
object you are, but build yourself anyway.&#8221; In an ordinary constructor,
the compiler must know which VTABLE <A NAME="Index668"></A>address to bind to
the VPTR<A NAME="Index669"></A>, and if it existed, a virtual constructor
couldn&#8217;t do this because it doesn&#8217;t know all the type information at
compile-time. It makes sense that a constructor can&#8217;t be virtual because
it is the one function that absolutely must know everything about the type of
the object.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">And yet there are times when you want
something approximating the behavior of a virtual constructor.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the <B>Shape</B> example, it would be
nice to hand the <B>Shape</B> constructor some specific information in the
argument list and let the constructor create a specific type of <B>Shape</B> (a
<B>Circle</B>, <B>Square</B>) with no further intervention. Ordinarily,
you&#8217;d have to make an explicit call to the <B>Circle</B>, <B>Square</B>
constructor yourself.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Coplien</FONT><A NAME="fnB29" HREF="#fn29">[29]</A><A NAME="Index670"></A><FONT FACE="Georgia">
calls his solution to this problem &#8220;envelope and letter classes.&#8221;
The &#8220;envelope&#8221; class is the base class, a shell that contains a
pointer to an object of the base class. The constructor for the
&#8220;envelope&#8221; determines (at runtime, when the constructor is called,
not at compile-time, when the type checking is normally done) what specific type
to make, then creates an object of that specific type (on the heap) and assigns
the object to its pointer. All the function calls are then handled by the base
class through its pointer. So the base class is acting as a proxy for the
derived class:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C11:VirtualConstructor.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;exception&gt;
#include &lt;vector&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Shape {
  Shape* s;
  <font color=#009900>// Prevent copy-construction &amp; operator=</font>
  Shape(Shape&amp;);
  Shape <font color=#0000ff>operator</font>=(Shape&amp;);
<font color=#0000ff>protected</font>:
  Shape() { s = 0; };
<font color=#0000ff>public</font>:
  <font color=#0000ff>virtual</font> <font color=#0000ff>void</font> draw() { s-&gt;draw(); }
  <font color=#0000ff>virtual</font> <font color=#0000ff>void</font> erase() { s-&gt;erase(); }
  <font color=#0000ff>virtual</font> <font color=#0000ff>void</font> test() { s-&gt;test(); };
  <font color=#0000ff>virtual</font> ~Shape() {
    cout &lt;&lt; <font color=#004488>"~Shape\n"</font>;
    <font color=#0000ff>if</font>(s) {
      cout &lt;&lt; <font color=#004488>"Making virtual call: "</font>;
      s-&gt;erase(); <font color=#009900>// Virtual call</font>
    }
    cout &lt;&lt; <font color=#004488>"delete s: "</font>;
    <font color=#0000ff>delete</font> s; <font color=#009900>// The polymorphic deletion</font>
  }
  <font color=#0000ff>class</font> BadShapeCreation : <font color=#0000ff>public</font> exception {
    string reason;
  <font color=#0000ff>public</font>:
    BadShapeCreation(string type) {
      reason = <font color=#004488>"Cannot create type "</font> + type;
    }
    ~BadShapeCreation() <font color=#0000ff>throw</font>() {}
    <font color=#0000ff>const</font> <font color=#0000ff>char</font> *what() <font color=#0000ff>const</font> <font color=#0000ff>throw</font>() { 
      <font color=#0000ff>return</font> reason.c_str(); 
    }
  };
  Shape(string type) <font color=#0000ff>throw</font>(BadShapeCreation);
};

<font color=#0000ff>class</font> Circle : <font color=#0000ff>public</font> Shape {
  Circle(Circle&amp;);
  Circle <font color=#0000ff>operator</font>=(Circle&amp;);
  Circle() {} <font color=#009900>// Private constructor</font>
  <font color=#0000ff>friend</font> <font color=#0000ff>class</font> Shape;
<font color=#0000ff>public</font>:
  <font color=#0000ff>void</font> draw() { cout &lt;&lt; <font color=#004488>"Circle::draw\n"</font>; }
  <font color=#0000ff>void</font> erase() { cout &lt;&lt; <font color=#004488>"Circle::erase\n"</font>; }
  <font color=#0000ff>void</font> test() { draw(); }
  ~Circle() { cout &lt;&lt; <font color=#004488>"Circle::~Circle\n"</font>; }
};

<font color=#0000ff>class</font> Square : <font color=#0000ff>public</font> Shape {
  Square(Square&amp;);
  Square <font color=#0000ff>operator</font>=(Square&amp;);
  Square() {}
  <font color=#0000ff>friend</font> <font color=#0000ff>class</font> Shape;
<font color=#0000ff>public</font>:
  <font color=#0000ff>void</font> draw() { cout &lt;&lt; <font color=#004488>"Square::draw\n"</font>; }
  <font color=#0000ff>void</font> erase() { cout &lt;&lt; <font color=#004488>"Square::erase\n"</font>; }
  <font color=#0000ff>void</font> test() { draw(); }
  ~Square() { cout &lt;&lt; <font color=#004488>"Square::~Square\n"</font>; }
};

Shape::Shape(string type) 
  <font color=#0000ff>throw</font>(Shape::BadShapeCreation) {
  <font color=#0000ff>if</font>(type == <font color=#004488>"Circle"</font>) 
    s = <font color=#0000ff>new</font> Circle;
  <font color=#0000ff>else</font> <font color=#0000ff>if</font>(type == <font color=#004488>"Square"</font>)
    s = <font color=#0000ff>new</font> Square;
  <font color=#0000ff>else</font> <font color=#0000ff>throw</font> BadShapeCreation(type);
  draw();  <font color=#009900>// Virtual call in the constructor</font>
}

<font color=#0000ff>char</font>* shlist[] = { <font color=#004488>"Circle"</font>, <font color=#004488>"Square"</font>, <font color=#004488>"Square"</font>,
  <font color=#004488>"Circle"</font>, <font color=#004488>"Circle"</font>, <font color=#004488>"Circle"</font>, <font color=#004488>"Square"</font>, <font color=#004488>""</font> };

<font color=#0

⌨️ 快捷键说明

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