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

📄 chap10.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>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Persistent {
  <font color=#0000ff>int</font> objSize; <font color=#009900>// Size of stored object</font>
<font color=#0000ff>public</font>:
  Persistent(<font color=#0000ff>int</font> sz) : objSize(sz) {}
  <font color=#0000ff>void</font> write(ostream&amp; out) <font color=#0000ff>const</font> {
    out.write((<font color=#0000ff>char</font>*)<font color=#0000ff>this</font>, objSize);
  }
  <font color=#0000ff>void</font> read(istream&amp; in) {
    in.read((<font color=#0000ff>char</font>*)<font color=#0000ff>this</font>, objSize);
  }
};

<font color=#0000ff>class</font> Data {
  <font color=#0000ff>float</font> f[3];
<font color=#0000ff>public</font>:
  Data(<font color=#0000ff>float</font> f0 = 0.0, <font color=#0000ff>float</font> f1 = 0.0,
    <font color=#0000ff>float</font> f2 = 0.0) {
    f[0] = f0;
    f[1] = f1;
    f[2] = f2;
  }
  <font color=#0000ff>void</font> print(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* msg = <font color=#004488>""</font>) <font color=#0000ff>const</font> {
    <font color=#0000ff>if</font>(*msg) cout &lt;&lt; msg &lt;&lt; <font color=#004488>"   "</font>;
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 3; i++)
      cout &lt;&lt; <font color=#004488>"f["</font> &lt;&lt; i &lt;&lt; <font color=#004488>"] = "</font>
           &lt;&lt; f[i] &lt;&lt; endl;
  }
};

<font color=#0000ff>class</font> WData1 : <font color=#0000ff>public</font> Persistent, <font color=#0000ff>public</font> Data {
<font color=#0000ff>public</font>:
  WData1(<font color=#0000ff>float</font> f0 = 0.0, <font color=#0000ff>float</font> f1 = 0.0,
    <font color=#0000ff>float</font> f2 = 0.0) : Data(f0, f1, f2),
    Persistent(<font color=#0000ff>sizeof</font>(WData1)) {}
};

<font color=#0000ff>class</font> WData2 : <font color=#0000ff>public</font> Data, <font color=#0000ff>public</font> Persistent {
<font color=#0000ff>public</font>:
  WData2(<font color=#0000ff>float</font> f0 = 0.0, <font color=#0000ff>float</font> f1 = 0.0,
    <font color=#0000ff>float</font> f2 = 0.0) : Data(f0, f1, f2),
    Persistent(<font color=#0000ff>sizeof</font>(WData2)) {}
};

<font color=#0000ff>int</font> main() {
  {
    ofstream f1(<font color=#004488>"f1.dat"</font>), f2(<font color=#004488>"f2.dat"</font>);
    assure(f1, <font color=#004488>"f1.dat"</font>); assure(f2, <font color=#004488>"f2.dat"</font>);
    WData1 d1(1.1, 2.2, 3.3);
    WData2 d2(4.4, 5.5, 6.6);
    d1.print(<font color=#004488>"d1 before storage"</font>);
    d2.print(<font color=#004488>"d2 before storage"</font>);
    d1.write(f1);
    d2.write(f2);
  } <font color=#009900>// Closes files</font>
  ifstream f1(<font color=#004488>"f1.dat"</font>), f2(<font color=#004488>"f2.dat"</font>);
  assure(f1, <font color=#004488>"f1.dat"</font>); assure(f2, <font color=#004488>"f2.dat"</font>);
  WData1 d1;
  WData2 d2;
  d1.read(f1);
  d2.read(f2);
  d1.print(<font color=#004488>"d1 after storage"</font>);
  d2.print(<font color=#004488>"d2 after storage"</font>);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In this very simple version, the
<B>Persistent::read(&#160;)</B> and <B>Persistent::write(&#160;)</B> functions
take the <B>this</B> pointer and call <B>iostream</B> <B>read(&#160;)</B> and
<B>write(&#160;)
<A NAME="Index629"></A><A NAME="Index630"></A><A NAME="Index631"></A></B>functions.
(Note that any type of <B>iostream</B> can be used). A more sophisticated
<B>Persistent</B> class would call a <B>virtual</B> <B>write(&#160;)</B>
function for each subobject.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">With the language features covered so far
in the book, the number of bytes in the object cannot be known by the
<B>Persistent</B> class so it is inserted as a constructor argument. (In Chapter
XX, <I>run-time type identification</I> shows how you can find the exact type of
an object given only a base pointer; once you have the exact type you can find
out the correct size with the <B>sizeof</B>
<A NAME="Index632"></A>operator.)</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>Data</B> class contains no
pointers or VPTR<A NAME="Index633"></A>, so there is no danger in simply writing
it to disk and reading it back again. And it works fine in class <B>WData1</B>
when, in <B>main(&#160;)</B>, it&#8217;s written to file F1.DAT and later read
back again. However, when <B>Persistent</B> is second in the inheritance list of
<B>WData2</B>, the <B>this</B> pointer for <B>Persistent</B> is offset to the
end of the object, so it reads and writes past the end of the object. This not
only produces garbage when reading the object from the file, it&#8217;s
dangerous because it walks over any storage that occurs after the
object.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This problem occurs in multiple
inheritance<A NAME="Index634"></A><A NAME="Index635"></A> any time a class must
produce the <B>this</B> pointer for the actual object from a subobject&#8217;s
<B>this </B>pointer. Of course, if you know your compiler always lays out
objects in order of declaration in the inheritance list, you can ensure that you
always put the critical class at the beginning of the list (assuming
there&#8217;s only one critical class). However, such a class may exist in the
inheritance hierarchy of another class and you may unwittingly put it in the
wrong place during multiple inheritance. Fortunately, using run-time type
identification<A NAME="Index636"></A> (the subject of Chapter XX) will produce
the proper pointer to the actual object, even if multiple inheritance is
used.</FONT><BR></P></DIV>
<A NAME="Heading319"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H4 ALIGN="LEFT">
Improved persistence<BR><A NAME="Index637"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A more practical approach to persistence,
and one you will see employed more often, is to create virtual functions in the
base class for reading and writing and then require the creator of any new class
that must be streamed to redefine these functions. The argument to the function
is the stream object to write to or read
from.</FONT><A NAME="fnB26" HREF="#fn26">[26]</A><FONT FACE="Georgia"> Then the
creator of the class, who knows best how the new parts should be read or
written, is responsible for making the correct function calls. This
doesn&#8217;t have the &#8220;magical&#8221; quality of the previous example,
and it requires more coding and knowledge on the part of the user, but it works
and doesn&#8217;t break when pointers are present:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C10:Persist2.cpp</font>
<font color=#009900>// Improved MI persistence</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include <font color=#004488>"..</font><font color=#004488>/require.h"</font>
#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;cstring&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Persistent {
<font color=#0000ff>public</font>:
  <font color=#0000ff>virtual</font> <font color=#0000ff>void</font> write(ostream&amp; out) <font color=#0000ff>const</font> = 0;
  <font color=#0000ff>virtual</font> <font color=#0000ff>void</font> read(istream&amp; in) = 0;
  <font color=#0000ff>virtual</font> ~Persistent() {}
};

<font color=#0000ff>class</font> Data {
<font color=#0000ff>protected</font>:
  <font color=#0000ff>float</font> f[3];
<font color=#0000ff>public</font>:
  Data(<font color=#0000ff>float</font> f0 = 0.0, <font color=#0000ff>float</font> f1 = 0.0,
    <font color=#0000ff>float</font> f2 = 0.0) {
    f[0] = f0;
    f[1] = f1;
    f[2] = f2;
  }
  <font color=#0000ff>void</font> print(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* msg = <font color=#004488>""</font>) <font color=#0000ff>const</font> {
    <font color=#0000ff>if</font>(*msg) cout &lt;&lt; msg &lt;&lt; endl;
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 3; i++)
      cout &lt;&lt; <font color=#004488>"f["</font> &lt;&lt; i &lt;&lt; <font color=#004488>"] = "</font>
           &lt;&lt; f[i] &lt;&lt; endl;
  }
};

<font color=#0000ff>class</font> WData1 : <font color=#0000ff>public</font> Persistent, <font color=#0000ff>public</font> Data {
<font color=#0000ff>public</font>:
  WData1(<font color=#0000ff>float</font> f0 = 0.0, <font color=#0000ff>float</font> f1 = 0.0,
    <font color=#0000ff>float</font> f2 = 0.0) : Data(f0, f1, f2) {}
  <font color=#0000ff>void</font> write(ostream&amp; out) <font color=#0000ff>const</font> {
    out &lt;&lt; f[0] &lt;&lt; <font color=#004488>" "</font> 
      &lt;&lt; f[1] &lt;&lt; <font color=#004488>" "</font> &lt;&lt; f[2] &lt;&lt; <font color=#004488>" "</font>;
  }
  <font color=#0000ff>void</font> read(istream&amp; in) {
    in &gt;&gt; f[0] &gt;&gt; f[1] &gt;&gt; f[2];
  }
};

<font color=#0000ff>class</font> WData2 : <font color=#0000ff>public</font> Data, <font color=#0000ff>public</font> Persistent {
<font color=#0000ff>public</font>:
  WData2(<font color=#0000ff>float</font> f0 = 0.0, <font color=#0000ff>float</font> f1 = 0.0,
    <font color=#0000ff>float</font> f2 = 0.0) : Data(f0, f1, f2) {}
  <font color=#0000ff>void</font> write(ostream&amp; out) <font color=#0000ff>const</font> {
    out &lt;&lt; f[0] &lt;&lt; <font color=#004488>" "</font> 
      &lt;&lt; f[1] &lt;&lt; <font color=#004488>" "</font> &lt;&lt; f[2] &lt;&lt; <font color=#004488>" "</font>;
  }
  <font color=#0000ff>void</font> read(istream&amp; in) {
    in &gt;&gt; f[0] &gt;&gt; f[1] &gt;&gt; f[2];
  }
};

<font color=#0000ff>class</font> Conglomerate : <font color=#0000ff>public</font> Data,
<font color=#0000ff>public</font> Persistent {
  <font color=#0000ff>char</font>* name; <font color=#009900>// Contains a pointer</font>
  WData1 d1;
  WData2 d2;
<font color=#0000ff>public</font>:
  Conglomerate(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* nm = <font color=#004488>""</font>,
    <font color=#0000ff>float</font> f0 = 0.0, <font color=#0000ff>float</font> f1 = 0.0,
    <font color=#0000ff>float</font> f2 = 0.0, <font color=#0000ff>float</font> f3 = 0.0,
    <font color=#0000ff>float</font> f4 = 0.0, <font color=#0000ff>float</font> f5 = 0.0,
    <font color=#0000ff>float</font> f6 = 0.0, <font color=#0000ff>float</font> f7 = 0.0,
    <font color=#0000ff>float</font> f8= 0.0) : Data(f0, f1, f2),
    d1(f3, f4, f5), d2(f6, f7, f8) {
    name = <font color=#0000ff>new</font> <font color=#0000ff>char</font>[strlen(nm) + 1];
    strcpy(name, nm);
  }
  <font color=#0000ff>void</font> write(ostream&amp; out) <font color=#0000ff>const</font> {
    <font color=#0000ff>int</font> i = strlen(name) + 1;
    out &lt;&lt; i &lt;&lt; <font color=#004488>" "</font>; <font color=#009900>// Store size of string</font>
    out &lt;&lt; name &lt;&lt; endl;
    d1.write(out);
    d2.write(out);
    out &lt;&lt; f[0] &lt;&lt; <font color=#004488>" "</font> &lt;&lt; f[1] &lt;&lt; <font color=#004488>" "</font> &lt;&lt; f[2];
  }
  <font color=#009900>// Must read in same order as write:</font>
  <font color=#0000ff>void</font> read(istream&amp; in) {
    <font color=#0000ff>delete</font> []name; <font color=#009900>// Remove old storage</font>
    <font color=#0000ff>int</font> i;
    in &gt;&gt; i &gt;&gt; ws; <font color=#009900>// Get int, strip whitespace</font>
    name = <font color=#0000ff>new</font> <font color=#0000ff>char</font>[i];
    in.getline(name, i);
    d1.read(in);
    d2.read(in);
    in &gt;&gt; f[0] &gt;&gt; f[1] &gt;&gt; f[2];
  }
  <font color=#0000ff>void</font> print() <font color=#0000ff>const</font> {
    Data::print(name);
    d1.print();
    d2.print();
  }
};

<font color=#0000ff>int</font> main() {
  {
    ofstream data(<font color=#004488>"data.dat"</font>);
    assure(data, <font color=#004488>"data.dat"</font>);
    Conglomerate C(<font color=#004488>"This is Conglomerate C"</font>,
      1.1, 2.2, 3.3, 4.4, 5.5,
      6.6, 7.7, 8.8, 9.9);
    cout &lt;&lt; <font color=#004488>"C before storage"</font> &lt;&lt; endl;
    C.print();

⌨️ 快捷键说明

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