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

📄 ch17.htm

📁 Why C++ is the emerging standard in software development. The steps to develop a C++ program. How
💻 HTM
📖 第 1 页 / 共 5 页
字号:
43:         // unsigned short itsLen;44:          int itsLen;45:    };46:    47:    // default constructor creates string of 0 bytes48:    String::String()49:    {50:       itsString = new char[1];51:       itsString[0] = `\0';52:       itsLen=0;53:       ASSERT(Invariants());54:    }55:    56:    // private (helper) constructor, used only by57:    // class methods for creating a new string of58:    // required size.  Null filled.59:    String::String(int len)60:    {61:       itsString = new char[len+1];62:       for (int i = 0; i&lt;=len; i++)63:          itsString[i] = `\0';64:       itsLen=len;65:       ASSERT(Invariants());66:    }67:    68:    // Converts a character array to a String69:    String::String(const char * const cString)70:    {71:       itsLen = strlen(cString);72:       itsString = new char[itsLen+1];73:       for (int i = 0; i&lt;itsLen; i++)74:          itsString[i] = cString[i];75:       itsString[itsLen]='\0';76:       ASSERT(Invariants());77:    }78:    79:    // copy constructor80:    String::String (const String &amp; rhs)81:    {82:       itsLen=rhs.GetLen();83:       itsString = new char[itsLen+1];84:       for (int i = 0; i&lt;itsLen;i++)85:          itsString[i] = rhs[i];86:       itsString[itsLen] = `\0';87:       ASSERT(Invariants());88:    }89:    90:    // destructor, frees allocated memory91:    String::~String ()92:    {93:       ASSERT(Invariants());94:       delete [] itsString;95:       itsLen = 0;96:    }97:    98:    // operator equals, frees existing memory99:    // then copies string and size100:    String&amp; String::operator=(const String &amp; rhs)101:    {102:       ASSERT(Invariants());103:       if (this == &amp;rhs)104:          return *this;105:       delete [] itsString;106:       itsLen=rhs.GetLen();107:       itsString = new char[itsLen+1];108:       for (int i = 0; i&lt;itsLen;i++)109:          itsString[i] = rhs[i];110:       itsString[itsLen] = `\0';111:       ASSERT(Invariants());112:       return *this;113:    }114:    115:    //non constant offset operator, returns116:    // reference to character so it can be117:    // changed!118:    char &amp; String::operator[](int offset)119:    {120:       ASSERT(Invariants());121:       if (offset &gt; itsLen)122:          return itsString[itsLen-1];123:       else124:          return itsString[offset];125:       ASSERT(Invariants());126:    }127:    128:    // constant offset operator for use129:    // on const objects (see copy constructor!)130:    char String::operator[](int offset) const131:    {132:       ASSERT(Invariants());133:       if (offset &gt; itsLen)134:          return itsString[itsLen-1];135:       else136:          return itsString[offset];137:       ASSERT(Invariants());138:    }139:    140:    141:    BOOL String::Invariants() const142:    {143:    #ifdef SHOW_INVARIANTS144:       cout &lt;&lt; &quot; String OK &quot;;145:    #endif146:        return ( (itsLen &amp;&amp; itsString) || 147:          (!itsLen &amp;&amp; !itsString) );148:     }149:    150:     class Animal151:     {152:     public:153:        Animal():itsAge(1),itsName(&quot;John Q. Animal&quot;)154:           {ASSERT(Invariants());}155:         Animal(int, const String&amp;);156:        ~Animal(){}157:        int GetAge() {  ASSERT(Invariants()); return itsAge;}158:        void SetAge(int Age) 159:        { 160:             ASSERT(Invariants()); 161:             itsAge = Age;              162:             ASSERT(Invariants()); 163:        }164:         String&amp; GetName() 165:         { 166:               ASSERT(Invariants()); 167:               return itsName;  168:         }169:         void SetName(const String&amp; name)170:               { 171:               ASSERT(Invariants()); 172:               itsName = name; 173:               ASSERT(Invariants());174:         }175:         BOOL Invariants();176:      private:177:         int itsAge;178:         String itsName;179:      };180:    181:      Animal::Animal(int age, const String&amp; name):182:      itsAge(age),183:      itsName(name)184:      {185:         ASSERT(Invariants());186:      }187:    188:      BOOL Animal::Invariants()189:      {190:      #ifdef SHOW_INVARIANTS191:         cout &lt;&lt; &quot; Animal OK &quot;;192:      #endif193:         return (itsAge &gt; 0 &amp;&amp; itsName.GetLen());194:      }195:    196:      int main()197:      {198:         Animal sparky(5,&quot;Sparky&quot;);199:         cout &lt;&lt; &quot;\n&quot; &lt;&lt; sparky.GetName().GetString() &lt;&lt; &quot; is &quot;;200:         cout &lt;&lt; sparky.GetAge() &lt;&lt; &quot; years old.&quot;;201:         sparky.SetAge(8);202:         cout &lt;&lt; &quot;\n&quot; &lt;&lt; sparky.GetName().GetString() &lt;&lt; &quot; is &quot;;203:         cout &lt;&lt; sparky.GetAge() &lt;&lt; &quot; years old.&quot;;204:         return 0;<TT>205: }</TT></FONT><FONT COLOR="#0066FF">Output: String OK  String OK  String OK  String OK  String OK  String OK  String OK  Animal OK  String OK  Animal OKSparky is  Animal OK 5 years old. Animal OK  Animal OK  Animal OK  Sparky is  Animal OK 8 years old. String OK </FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On lines 6-16, the <TT>assert()</TT>macro is defined. If <TT>DEBUG</TT> is defined, this will write out an error messagewhen the <TT>assert()</TT> macro evaluates <TT>FALSE</TT>.<BR>On line 38, the <TT>String</TT> class member function <TT>Invariants()</TT> is declared;it is defined on lines 141-148. The constructor is declared on lines 48-54, and online 53, after the object is fully constructed, <TT>Invariants()</TT> is called toconfirm proper construction.</P><P>This pattern is repeated for the other constructors, and the destructor calls<TT>Invariants()</TT> only before it sets out to destroy the object. The remainingclass functions call <TT>Invariants()</TT> both before taking any action and thenagain before returning. This both affirms and validates a fundamental principal ofC++: Member functions other than constructors and destructors should work on validobjects and should leave them in a valid state.</P><P>On line 175, class <TT>Animal</TT> declares its own <TT>Invariants()</TT> method,implemented on lines 188-194. Note on lines 154, 157, 160, and 162 that inline functionscan call the <TT>Invariants()</TT> method.<H4 ALIGN="CENTER"><A NAME="Heading36"></A><FONT COLOR="#000077">Printing InterimValues</FONT></H4><P>In addition to asserting that something is true using the <TT>assert()</TT> macro,you may want to print the current value of pointers, variables, and strings. Thiscan be very helpful in checking your assumptions about the progress of your program,and in locating off-by-one bugs in loops. Listing 17.7 illustrates this idea.</P><P><A NAME="Heading37"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 17.7. Printingvalues in DEBUG mode.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     // Listing 17.7 - Printing values in DEBUG mode2:     #include &lt;iostream.h&gt;3:     #define DEBUG4:5:     #ifndef DEBUG6:     #define PRINT(x)7:     #else8:     #define PRINT(x) \9:        cout &lt;&lt; #x &lt;&lt; &quot;:\t&quot; &lt;&lt; x &lt;&lt; endl;10:    #endif11:12:    enum BOOL { FALSE, TRUE } ;13:14:    int main()15:    {16:       int x = 5;17:       long y = 73898l;18:       PRINT(x);19:       for (int i = 0; i &lt; x; i++)20:       {21:          PRINT(i);22:       }23:24:       PRINT (y);25:       PRINT(&quot;Hi.&quot;);26:       int *px = &amp;x;27:       PRINT(px);28:       PRINT (*px);29:     return 0;<TT>30: }</TT></FONT><FONT COLOR="#0066FF">Output: x:      5i:      0i:      1i:      2i:      3i:      4y:      73898&quot;Hi.&quot;:  Hi.px:       0x2100 (You may receive a value other than 0x2100)*px:    5</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The macro on lines 5-10 providesprinting of the current value of the supplied parameter. Note that the first thingfed to <TT>cout</TT> is the stringized version of the parameter; that is, if youpass in <TT>x</TT>, <TT>cout</TT> receives <TT>&quot;x&quot;</TT>.<BR><BR>Next, <TT>cout</TT> receives the quoted string <TT>&quot;:\t&quot;</TT>, which printsa colon and then a tab. Third, <TT>cout</TT> receives the value of the parameter(<TT>x</TT>), and then finally, <TT>endl</TT>, which writes a new line and flushesthe buffer.<H4 ALIGN="CENTER"><A NAME="Heading39"></A><FONT COLOR="#000077">Debugging Levels</FONT></H4><P>In large, complex projects, you may want more control than simply turning <TT>DEBUG</TT>on and off. You can define debug levels and test for these levels when deciding whichmacros to use and which to strip out.</P><P>To define a level, simply follow the <TT>#define DEBUG</TT> statement with a number.While you can have any number of levels, a common system is to have four levels:<TT>HIGH</TT>, <TT>MEDIUM</TT>, <TT>LOW</TT>, and <TT>NONE</TT>. Listing 17.8 illustrateshow this might be done, using the <TT>String</TT> and <TT>Animal</TT> classes fromListing 17.6. The definitions of the class methods other than <TT>Invariants()</TT>have been left out to save space because they are unchanged from Listing 17.6.<BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>To compile this code, copy lines	43-136 of Listing 17.6 between lines 64 and 65 of this listing. <HR></BLOCKQUOTE><P><A NAME="Heading40"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 17.8. Levelsof debugging.</B></FONT></P><PRE><FONT COLOR="#0066FF">0:    enum LEVEL { NONE, LOW, MEDIUM, HIGH };1:    const int FALSE = 0;2:    const int TRUE = 1;3:    typedef int BOOL;4:    5:     #define DEBUGLEVEL HIGH6:    7:     #include &lt;iostream.h&gt;8:     #include &lt;string.h&gt;9:    10:     #if DEBUGLEVEL &lt; LOW  // must be medium or high11:     #define ASSERT(x)

⌨️ 快捷键说明

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