?? ch08.htm
字號:
23 cout << "Destructor called.\n";
24 }
25
26 int main()
27 {
28 cout << "SimpleCat Frisky...\n";
29 SimpleCat Frisky;
30 cout << "SimpleCat *pRags = new SimpleCat...\n";
31 SimpleCat * pRags = new SimpleCat;
32 cout << "delete pRags...\n";
33 delete pRags;
34 cout << "Exiting, watch Frisky go...\n";
35 return 0;
<TT>36 }</TT></FONT>
<FONT COLOR="#0066FF">
Output: SimpleCat Frisky...
Constructor called.
SimpleCat *pRags = new SimpleCat..
Constructor called.
delete pRags...
Destructor called.
Exiting, watch Frisky go...
Destructor called.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Lines 6-13 declare the stripped-down
class <TT>SimpleCat</TT>. Line 9 declares <TT>SimpleCat</TT>'s constructor, and lines
15-19 contain its definition. Line 10 declares <TT>SimpleCat</TT>'s destructor, and
lines 21-24 contain its definition.<BR>
In line 29, <TT>Frisky</TT> is created on the stack, which causes the constructor
to be called. In line 31, the <TT>SimpleCat</TT> pointed to by <TT>pRags</TT> is
created on the heap; the constructor is called again. In line 33, delete is called
on <TT>pRags</TT>, and the destructor is called. When the function ends, <TT>Frisky</TT>
goes out of scope, and the destructor is called.
<H3 ALIGN="CENTER"><A NAME="Heading30"></A><FONT COLOR="#000077">Accessing Data Members</FONT></H3>
<P>You accessed data members and functions by using the dot (<TT>.</TT>) operator
for <TT>Cat</TT> objects created locally. To access the <TT>Cat</TT> object on the
free store, you must dereference the pointer and call the dot operator on the object
pointed to by the pointer. Therefore, to access the <TT>GetAge</TT> member function,
you would write</P>
<PRE><FONT COLOR="#0066FF"> (*pRags).GetAge();
</FONT></PRE>
<P>Parentheses are used to assure that <TT>pRags</TT> is dereferenced before <TT>GetAge()</TT>
is accessed.</P>
<P>Because this is cumbersome, C++ provides a shorthand operator for indirect access:
the <TT>points-to</TT> operator (<TT>-></TT>), which is created by typing the
dash (<TT>-</TT>) immediately followed by the greater-than symbol (<TT>></TT>).
C++ treats this as a single symbol. Listing 8.6 demonstrates accessing member variables
and functions of objects created on the free store.</P>
<P><A NAME="Heading31"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.6. Accessing
member data of objects on the free store.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">
1: // Listing 8.6
2: // Accessing data members of objects on the heap
3:
4: #include <iostream.h>
5:
6: class SimpleCat
7: {
8: public:
9: SimpleCat() {itsAge = 2; }
10: ~SimpleCat() {}
11: int GetAge() const { return itsAge; }
12: void SetAge(int age) { itsAge = age; }
13: private:
14: int itsAge;
15: };
16:
17: int main()
18: {
19: SimpleCat * Frisky = new SimpleCat;
20: cout << "Frisky is " << Frisky->GetAge() << " years old\n";
21: Frisky->SetAge(5);
22: cout << "Frisky is " << Frisky->GetAge() << " years old\n";
23: delete Frisky;
24: return 0;
<TT>25: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: Frisky is 2 years old
Frisky is 5 years old
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>In line 19, a <TT>SimpleCat</TT>
object is instantiated on the free store. The default constructor sets its age to
<TT>2</TT>, and the <TT>GetAge()</TT> method is called in line 20. Because this is
a pointer, the indirection operator (<TT>-></TT>) is used to access the member
data and functions. In line 21, the <TT>SetAge()</TT> method is called, and <TT>GetAge()</TT>
is accessed again in line 22.
<H3 ALIGN="CENTER"><A NAME="Heading33"></A><FONT COLOR="#000077">Member Data on the
Free Store</FONT></H3>
<P>One or more of the data members of a class can be a pointer to an object on the
free store. The memory can be allocated in the class constructor or in one of its
methods, and it can be deleted in its destructor, as Listing 8.7 illustrates.</P>
<P><A NAME="Heading34"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.7. Pointers
as member data.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: // Listing 8.7
2: // Pointers as data members
3:
4: #include <iostream.h>
5:
6: class SimpleCat
7: {
8: public:
9: SimpleCat();
10: ~SimpleCat();
11: int GetAge() const { return *itsAge; }
12: void SetAge(int age) { *itsAge = age; }
13:
14: int GetWeight() const { return *itsWeight; }
15: void setWeight (int weight) { *itsWeight = weight; }
16:
17: private:
18: int * itsAge;
19: int * itsWeight;
20: };
21:
22: SimpleCat::SimpleCat()
23: {
24: itsAge = new int(2);
25: itsWeight = new int(5);
26: }
27:
28: SimpleCat::~SimpleCat()
29: {
30: delete itsAge;
31: delete itsWeight;
32: }
33:
34: int main()
35: {
36: SimpleCat *Frisky = new SimpleCat;
37: cout << "Frisky is " << Frisky->GetAge() << " years old\n";
38: Frisky->SetAge(5);
39: cout << "Frisky is " << Frisky->GetAge() << " years old\n";
40: delete Frisky;
41: return 0;
<TT>42: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: Frisky is 2 years old
Frisky is 5 years old
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The class <TT>SimpleCat</TT>
is declared to have two member variables--both of which are pointers to integers--on
lines 14 and 15. The constructor (lines 22-26) initializes the pointers to memory
on the free store and to the default values.<BR>
The destructor (lines 28-32) cleans up the allocated memory. Because this is the
destructor, there is no point in assigning these pointers to <TT>null</TT>, as they
will no longer be accessible. This is one of the safe places to break the rule that
deleted pointers should be assigned to <TT>null</TT>, although following the rule
doesn't hurt.</P>
<P>The calling function (in this case, <TT>main()</TT>) is unaware that <TT>itsAge</TT>
and <TT>itsWeight</TT> are point-ers to memory on the free store. <TT>main()</TT>
continues to call <TT>GetAge()</TT> and <TT>SetAge()</TT>, and the details of the
memory management are hidden in the implementation of the class--as they should be.</P>
<P>When <TT>Frisky</TT> is deleted in line 40, its destructor is called. The destructor
deletes each of its member pointers. If these, in turn, point to objects of other
user-defined classes, their destructors are called as well.
<H3 ALIGN="CENTER"><A NAME="Heading36"></A><FONT COLOR="#000077">The this Pointer</FONT></H3>
<P>Every class member function has a hidden parameter: the <TT>this</TT> pointer.
<TT>this</TT> points to the individual object. Therefore, in each call to <TT>GetAge()</TT>
or <TT>SetAge()</TT>, the <TT>this</TT> pointer for the object is included as a hidden
parameter.</P>
<P>It is possible to use the <TT>this</TT> pointer explicitly, as Listing 8.8 illustrates.</P>
<P><A NAME="Heading37"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.8. Using the
this pointer.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">
1: // Listing 8.8
2: // Using the this pointer
3:
4: #include <iostream.h>
5:
6: class Rectangle
7: {
8: public:
9: Rectangle();
10: ~Rectangle();
11: void SetLength(int length) { this->itsLength = length; }
12: int GetLength() const { return this->itsLength; }
13:
14: void SetWidth(int width) { itsWidth = width; }
15: int GetWidth() const { return itsWidth; }
16:
17: private:
18: int itsLength;
19: int itsWidth;
20: };
21:
22: Rectangle::Rectangle()
23: {
24: itsWidth = 5;
25: itsLength = 10;
26: }
27: Rectangle::~Rectangle()
28: {}
29:
30: int main()
31: {
32: Rectangle theRect;
33: cout << "theRect is " << theRect.GetLength() << " feet long.\n";
34: cout << "theRect is " << theRect.GetWidth() << " feet wide.\n";
35: theRect.SetLength(20);
36: theRect.SetWidth(10);
37: cout << "theRect is " << theRect.GetLength()<< " feet long.\n";
38: cout << "theRect is " << theRect.GetWidth()<< " feet wide.\n";
39: return 0;
<TT>40: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: theRect is 10 feet long.
theRect is 5 feet long.
theRect is 20 feet long.
theRect is 10 feet long.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis: </B></FONT>The <TT>SetLength()</TT> and <TT>GetLength()</TT>
accessor functions explicitly use the <TT>this</TT> pointer to access the member
variables of the <TT>Rectangle</TT> object. The <TT>SetWidth</TT> and <TT>GetWidth</TT>
accessors do not. There is no difference in their behavior, although the syntax is
easier to understand.<BR>
If that were all there was to the <TT>this</TT> pointer, there would be little point
in bothering you with it. The <TT>this</TT> pointer, however, is a pointer; it stores
the memory address of an object. As such, it can be a powerful tool.</P>
<P>You'll see a practical use for the <TT>this</TT> pointer on Day 10, "Advanced
Functions," when operator overloading is discussed. For now, your goal is to
know about the <TT>this</TT> pointer and to understand what it is: a pointer to the
object itself.</P>
<P>You don't have to worry about creating or deleting the <TT>this</TT> pointer.
The compiler takes care of that.
<H3 ALIGN="CENTER"><A NAME="Heading39"></A><FONT COLOR="#000077">Stray or Dangling
Pointers</FONT></H3>
<P>One source of bugs that are nasty and difficult to find is stray pointers. A stray
pointer is created when you call <TT>delete</TT> on a pointer--thereby freeing the
memory that it points to--and later try to use that pointer again without reassigning
it.</P>
<P>It is as though the Acme Mail Order company moved away, and you still pressed
the programmed button on your phone. It is possible that nothing terrible happens--a
telephone rings in a deserted warehouse. Perhaps the telephone number has been reassigned
to a munitions factory, and your call detonates an explosive and blows up your whole
city!</P>
<P>In short, be careful not to use a pointer after you have called <TT>delete</TT>
on it. The pointer still points to the old area of memory, but the compiler is free
to put other data there; using the pointer can cause your program to crash. Worse,
your program might proceed merrily on its way and crash several minutes later. This
is called a time bomb, and it is no fun. To be safe, after you delete a pointer,
set it to <TT>null</TT> (<TT>0</TT>). This disarms the pointer.
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Stray pointers are often called
wild pointers or dangling pointers.
<HR>
</BLOCKQUOTE>
<P>Listing 8.9 illustrates creating a stray pointer.
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>WARNING:</B></FONT><B> </B>This program intentionally creates
a stray pointer. Do NOT run this program--it will crash, if you are lucky.
<HR>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -