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

📄 ch06.htm

📁 good book for learning c++ standard language
💻 HTM
📖 第 1 页 / 共 5 页
字号:
63:    Frisky.SetAge(7);
64:    cout << "Now Frisky is " ;
65:    cout << Frisky.GetAge() << " years old.\n";
66;     return 0;
<TT>67: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: Meow.
Frisky is a cat who is 5 years old.
Meow.
Now Frisky is 7 years old.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 6.4 is similar to
6.3, except that line 9 adds a constructor that takes an integer. Line 10 declares
the destructor, which takes no parameters. Destructors never take parameters, and
neither constructors nor destructors return a value--not even <TT>void</TT>.<BR>
Lines 19-22 show the implementation of the constructor. It is similar to the implementation
of the <TT>SetAge()</TT> accessor function. There is no return value.</P>
<P>Lines 24-26 show the implementation of the destructor <TT>~Cat()</TT>. This function
does nothing, but you must include the definition of the function if you declare
it in the class declaration.</P>
<P>Line 58 contains the definition of a <TT>Cat</TT> object, <TT>Frisky</TT>. The
value <TT>5</TT> is passed in to <TT>Frisky</TT>'s constructor. There is no need
to call <TT>SetAge()</TT>, because Frisky was created with the value <TT>5</TT> in
its member variable <TT>itsAge</TT>, as shown in line 61. In line 63, Frisky's <TT>itsAge</TT>
variable is reassigned to 7. Line 65 prints the new value.


<BLOCKQUOTE>
	<P>
<HR>
<B>DO </B>use constructors to initialize your objects. <B>DON'T </B>give constructors
	or destructors a return value. <B>DON'T</B> give destructors parameters. 
<HR>


</BLOCKQUOTE>

<H3 ALIGN="CENTER"><A NAME="Heading28"></A><FONT COLOR="#000077">const Member Functions</FONT></H3>
<P>If you declare a class method <TT>const</TT>, you are promising that the method
won't change the value of any of the members of the class. To declare a class method
constant, put the keyword <TT>const</TT> after the parentheses but before the semicolon.
The declaration of the constant member function <TT>SomeFunction()</TT> takes no
arguments and returns <TT>void</TT>. It looks like this:</P>
<PRE><FONT COLOR="#0066FF">void SomeFunction() const;
</FONT></PRE>
<P>Accessor functions are often declared as constant functions by using the <TT>const</TT>
modifier. The <TT>Cat</TT> class has two accessor functions:</P>
<PRE><FONT COLOR="#0066FF">void SetAge(int anAge);
int GetAge();
</FONT></PRE>
<P><TT>SetAge()</TT> cannot be <TT>const</TT> because it changes the member variable
<TT>itsAge</TT>. <TT>GetAge()</TT>, on the other hand, can and should be <TT>const</TT>
because it doesn't change the class at all. <TT>GetAge()</TT> simply returns the
current value of the member variable <TT>itsAge</TT>. Therefore, the declaration
of these functions should be written like this:</P>
<PRE><FONT COLOR="#0066FF">void SetAge(int anAge);
int GetAge() const;
</FONT></PRE>
<P>If you declare a function to be <TT>const</TT>, and the implementation of that
function changes the object by changing the value of any of its members, the compiler
flags it as an error. For example, if you wrote <TT>GetAge()</TT> in such a way that
it kept count of the number of times that the <TT>Cat</TT> was asked its age, it
would generate a compiler error. This is because you would be changing the <TT>Cat</TT>
object by calling this method.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Use <TT>const</TT> whenever possible.
	Declare member functions to be <TT>const</TT> whenever they should not change the
	object. This lets the compiler help you find errors; it's faster and less expensive
	than doing it yourself. 
<HR>


</BLOCKQUOTE>

<P>It is good programming practice to declare as many methods to be <TT>const</TT>
as possible. Each time you do, you enable the compiler to catch your errors, instead
of letting your errors become bugs that will show up when your program is running.
<H3 ALIGN="CENTER"><A NAME="Heading29"></A><FONT COLOR="#000077">Interface Versus
Implementation</FONT></H3>
<P>As you've learned, clients are the parts of the program that create and use objects
of your class. You can think of the interface to your class--the class declaration--as
a contract with these clients. The contract tells what data your class has available
and how your class will behave.</P>
<P>For example, in the <TT>Cat</TT> class declaration, you create a contract that
every <TT>Cat</TT> will have a member variable <TT>itsAge</TT> that can be initialized
in its constructor, assigned to by its <TT>SetAge()</TT> accessor function, and read
by its <TT>GetAge()</TT> accessor. You also promise that every <TT>Cat</TT> will
know how to <TT>Meow()</TT>.</P>
<P>If you make <TT>GetAge()</TT> a <TT>const</TT> function--as you should--the contract
also promises that <TT>GetAge()</TT> won't change the <TT>Cat</TT> on which it is
called.</P>
<P>C++ is strongly typed, which means that the compiler enforces these contracts
by giving you a compiler error when you violate them. Listing 6.5 demonstrates a
program that doesn't compile because of violations of these contracts.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>WARNING:</B></FONT><B> </B>Listing 6.5 does not compile!
	
<HR>


</BLOCKQUOTE>

<P><A NAME="Heading30"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 6.5. A demonstration
of violations of the interface</B></FONT><FONT SIZE="2" COLOR="#000077"><B>.</B></FONT><FONT
COLOR="#0066FF"></FONT>
<PRE><FONT COLOR="#0066FF">1:   // Demonstrates compiler errors
2:
3:
4:   #include &lt;iostream.h&gt;          // for cout
5:
6:  class Cat
7:  {
8:   public:
9:      Cat(int initialAge);
10:     ~Cat();
11:     int GetAge() const;          // const accessor function
12:     void SetAge (int age);
13:     void Meow();
14:  private:
15:    int itsAge;
16: };
17:
18:    // constructor of Cat,
19:    Cat::Cat(int initialAge)
20:    {
21:       itsAge = initialAge;
21:       cout &lt;&lt; &quot;Cat Constructor\n&quot;;
22:    }
23:
24:    Cat::~Cat()                   // destructor, takes no action
25:    {
26:       cout &lt;&lt; &quot;Cat Destructor\n&quot;;
27:    }
28:   // GetAge, const function
29:   // but we violate const!
30:   int Cat::GetAge() const
31:   {
32:      return (itsAge++);         // violates const!
33:   }
34:
35:   // definition of SetAge, public
36:   // accessor function
37:
38:   void Cat::SetAge(int age)
39:   {
40:      // set member variable its age to
41:      // value passed in by parameter age
42:      itsAge = age;
43:   }
44:
45:  // definition of Meow method
46:  // returns: void
47:  // parameters: None
48:  // action: Prints &quot;meow&quot; to screen
49:  void Cat::Meow()
50:  {
51:     cout &lt;&lt; &quot;Meow.\n&quot;;
52:  }
53:
54:  // demonstrate various violations of the
55   // interface, and resulting compiler errors
56:  int main()
57:  {
58:     Cat Frisky;                 // doesn't match declaration
59:     Frisky.Meow();
60:     Frisky.Bark();              // No, silly, cat's can't bark.
61:     Frisky.itsAge = 7;          // itsAge is private
62:      return 0;
<TT>63: }</TT></FONT> 
</PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>As it is written, this program
doesn't compile. Therefore, there is no output.<BR>
This program was fun to write because there are so many errors in it.</P>
<P>Line 11 declares <TT>GetAge()</TT> to be a <TT>const</TT> accessor function--as
it should be. In the body of <TT>GetAge()</TT>, however, in line 32, the member variable
<TT>itsAge</TT> is incremented. Because this method is declared to be <TT>const</TT>,
it must not change the value of <TT>itsAge</TT>. Therefore, it is flagged as an error
when the program is compiled.</P>
<P>In line 13, <TT>Meow()</TT> is not declared <TT>const</TT>. Although this is not
an error, it is bad programming practice. A better design takes into account that
this method doesn't change the member variables of <TT>Cat</TT>. Therefore, <TT>Meow()</TT>
should be <TT>const</TT>.</P>
<P>Line 58 shows the definition of a <TT>Cat</TT> object, <TT>Frisky</TT>. <TT>Cat</TT>s
now have a constructor, which takes an integer as a parameter. This means that you
must pass in a parameter. Because there is no parameter in line 58, it is flagged
as an error.</P>
<P>Line 60 shows a call to a class method, <TT>Bark()</TT>. <TT>Bark()</TT> was never
declared. Therefore, it is illegal.</P>
<P>Line 61 shows <TT>itsAge</TT> being assigned the value <TT>7</TT>. Because <TT>itsAge</TT>
is a private data member, it is flagged as an error when the program is compiled.
<H3 ALIGN="CENTER"><A NAME="Heading32"></A><FONT COLOR="#000077">Why Use the Compiler
to Catch Errors?</FONT></H3>
<P>While it would be wonderful to write 100 percent bug-free code, few programmers
have been able to do so. However, many programmers have developed a system to help
minimize bugs by catching and fixing them early in the process. Although compiler
errors are infuriating and are the bane of a programmer's existence, they are far
better than the alternative. A weakly typed language enables you to violate your
contracts without a peep from the compiler, but your program will crash at run-time--when,
for example, your boss is watching. Compile-time errors--that is, errors found while
you are compiling--are far better than run-time errors--that is, errors found while
you are executing the program. This is because compile-time errors can be found much
more reliably. It is possible to run a program many times without going down every
possible code path. Thus, a run-time error can hide for quite a while. Compile-time
errors are found every time you compile. Thus, they are easier to identify and fix.
It is the goal of quality programming to ensure that the code has no runtime bugs.
One tried-and-true technique to accomplish this is to use the compiler to catch your
mistakes early in the development process.
<H3 ALIGN="CENTER"><A NAME="Heading33"></A><FONT COLOR="#000077">Where to Put Class
Declarations and Method Definitions</FONT></H3>
<P>Each function that you declare for your class must have a definition. The definition
is also called the function implementation. Like other functions, the definition
of a class method has a function header and a function body.</P>
<P>The definition must be in a file that the compiler can find. Most C++ compilers
want that file to end with <TT>.C</TT> or <TT>.CPP</TT>. This book uses <TT>.CPP</TT>,
but check your compiler to see what it prefers.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE</B></FONT><B>: </B>Many compilers assume that files
	ending with <TT>.C</TT> are C programs, and that C++ program files end with <TT>.CPP</TT>.
	You can use any extension, but <TT>.CPP</TT> will minimize confusion. 
<HR>


</BLOCKQUOTE>

<P>You are free to put the declaration in this file as well, but that is not good
programming practice. The convention that most programmers adopt is to put the declaration
into what is called a header file, usually with the same name but ending in <TT>.H</TT>,
<TT>.HP</TT>, or <TT>.HPP</TT>. This book names the header files with <TT>.HPP</TT>,
but check your compiler to see what it prefers.</P>
<P>For example, you put the declaration of the <TT>Cat</TT> class into a file named
<TT>CAT.HPP</TT>, and you put the definition of the class methods into a file called
<TT>CAT.CPP</TT>. You then attach the header file to the <TT>.CPP</TT> file by putting
the following code at the top of <TT>CAT.CPP</TT>:</P>
<PRE><FONT COLOR="#0066FF">#include Cat.hpp
</FONT></PRE>
<P>This tells the compiler to read <TT>CAT.HPP</TT> into the file, just as if you
had typed in its contents at this point. Why bother separating them if you're just
going to read them back in? Most of the time, clients of your class don't care about
the implementation specifics. Reading the header file tells them everything they
need to know; they can ignore the implementation files.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The declaration of a class tells
	the compiler what the class is, what data it holds, and what functions it has. The
	declaration of the class is called its interface because it tells the user how to
	interact with the class. The interface is usually stored in an <TT>.HPP</TT> file,
	which is referred to as a header file. The function definition tells the compiler
	how the function works. The function definition is called the implementation of the
	class method, and it is kept in a <TT>.CPP</TT> file. The implementation details
	of the class are of concern only to the author of the class. Clients of the class--that
	is, the parts of the program that use the class--don't need to know, and don't care,
	how the functions are implemented. 
<HR>


</BLOCKQUOTE>

⌨️ 快捷键说明

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