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

📄 ch20.htm

📁 好书《C++ Builder高级编程技术》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
	Creating computerized representations of physical objects is a very common use of
	OOP, but it is not the primary reason for the existence of this technology. 
The great
	benefits of OOP are related to the reuse, design, and maintenance of software. Using
	OOP to represent real-world objects is only one branch of this field of knowledge.
	
<HR>


</BLOCKQUOTE>

<P>Note that object hierarchies always move 
from the general to the specific:</P>
<PRE><FONT COLOR="#0066FF">TWidget

TSiliconChip

TPentiumChip

</FONT></PRE>
<P>The underlying logic is simple enough:

<DL>
	<DD><B>1.</B> A <TT>TWidget</TT> could be almost any object that is bought and 
sold.<BR>
	<BR>
	<B>2.</B> A <TT>TSiliconChip</TT> is some kind of silicon-based entity.<BR>
	<BR>
	<B>3.</B> A <TT>TPentiumChip</TT> is a specific kind of computer chip that has a
	real-world counterpart.
</DL>

<P>The movement is from the abstract 
to the specific. It is almost always a mistake
to embody specific traits of an object in a base class for a hierarchy. Instead,
these early building blocks should be so broad in scope that they can serve as parents
to a wide variety of related objects 
or tools.</P>
<P>The main reason for this rule might not become apparent to all readers until they
have seen Chapter 21. The condensed explanation, however, looks like this:

<UL>
	<LI><TT>TWidget</TT> encapsulates certain basic functionality that 
applies to all
	widgets. For instance, all widgets might keep track of the date they were created,
	whereas only certain types of widgets might support the MX instruction set. Therefore,
	you can use polymorphism to ask all your widgets certain basic 
questions, such as
	when they were created. Conversely, there are certain types of questions you can
	ask only of widgets that are also computer processors. This system would not work
	if you did not move from the general to the specific. In short, 
you want all widgets
	to have certain basic functionality, and then as you move up the hierarchy, you can
	provide specific domains of knowledge or functionality to particular types of objects.
</UL>

<P>The Widget1 program found on the CD that 
accompanies this book includes a declaration
for class <TT>TWidget</TT>. (See Listing 20.1.) This declaration appears in a file
called <TT>Widgets.h</TT>. <TT>TWidget</TT> descends from the VCL class called <TT>TCustomControl</TT>
and uses a 
descendant of <TT>THierarchy</TT> through aggregation. As a result, you
will need to add both <TT>MyObject</TT> and the new Widgets files to your projects.</P>
<P>I have created a new file called Widgets because I am building a new type of object
that 
is distinct from <TT>THierarchy</TT> and <TT>TMyObject</TT>. I could, of course,
have put all the objects in one file, but I thought it made more sense to separate
the different types of objects into different files. There is no hard-and-fast rule

governing this kind of decision, and you can take whichever course makes sense to
you on a case-by-case basis.</P>
<P>I have also added a new class to <TT>TMyObject</TT>:</P>
<PRE><FONT COLOR="#0066FF">class TListHierarchy: public TMyObject

{


private:

  TStringList *FList;

protected:

  virtual void PrintString(AnsiString S)

    { FList-&gt;Add(S); }

public:

  TListHierarchy() { FList = new TStringList(); }

  __fastcall virtual ~TListHierarchy() { delete FList; }

  TStringList 
*GetHierarchy(TObject *AnObject)

    { ShowHierarchy(AnObject); return FList; }

};

</FONT></PRE>
<P>As you can see, this class stores its information in a <TT>TStringList</TT>. You
can retrieve the list from the class by using the 
<TT>GetHierarchy</TT> method:</P>
<PRE><FONT COLOR="#0066FF">ListBox1-&gt;Items = MyWidget-&gt;GetHierarchy();

</FONT></PRE>
<P>After you make this call, the list box referenced in the code would contain an
object hierarchy.
<H4><A 
NAME="Heading9"></A><FONT COLOR="#000077">TWidget and Its Destructor</FONT></H4>
<P>The Widgets unit is very simple at this point. To create it, I went to the files
menu and chose New Unit. I then saved the file as <TT>Widgets.cpp</TT> and edited
the 
header so that it looked like this:</P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////

// Widgets.h

// Learning how to use objects

// Copyright (c) 1997 by Charlie Calvert

//

#ifndef WidgetsH

#define WidgetsH

#include 
&quot;myobject.h&quot;

class TWidget: public TCustomControl

{

private:

  TListHierarchy *Hierarchy;

public:

  virtual __fastcall TWidget(TComponent *AOwner): TCustomControl(AOwner)

    { Hierarchy = new TListHierarchy; }

  virtual __fastcall 
~TWidget()

    { delete Hierarchy; }

  TStringList *GetHierarchy()

    { return Hierarchy-&gt;GetHierarchy(this); }

};

#endif

</FONT></PRE>
<P>This object uses aggregation to enlist the functionality of the <TT>TListHierarchy</TT>
object for its 
own purposes. In particular, it declares the object as private data
and then allocates memory for it in its constructor, and deallocates memory in its
destructor:</P>
<PRE><FONT COLOR="#0066FF">virtual __fastcall ~TWidget()

    { delete Hierarchy; }


</FONT></PRE>


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>A destructor is declared by writing
	the name of the object with a tilde prefaced to it: <TT>~TWidget</TT>. You rarely
	have reason to call a destructor 
explicitly. Instead, a destructor is called automatically
	when you use the <TT>delete</TT> operator on the entire object, when you call Free,
	or when a local object goes out of scope:</P>
	<PRE><FONT COLOR="#0066FF">delete MyWidget; // Automatically 
calls the destructor</FONT></PRE>
	<P>Destructors exist so you can have a place to deallocate any memory associated
	with an object, or to perform any other cleanup chores. The destructor exists for
	your convenience and serves no other purpose than 
to give you a chance to clean up
	before your object shuts down. <BR>
	<BR>
	All VCL objects inherit a virtual destructor declared in <TT>TObject</TT>. If you
	create a destructor for one of your own VCL objects, it must have the same signature
	used 
by the destructor in the <TT>TWidget</TT> object. That is, it must be declared
	as virtual <TT>__fastcall</TT>. This is because of the precedent set by the destructor
	found in <TT>TObject</TT>. 
<HR>


</BLOCKQUOTE>

<P>The <TT>GetHierarchy</TT> 
method of <TT>TWidget</TT> returns the result of a call
to the <TT>Hierarchy::GetHierarchy</TT> method:</P>
<PRE><FONT COLOR="#0066FF">TStringList *GetHierarchy()

    { return Hierarchy-&gt;GetHierarchy(this); }

</FONT></PRE>
<P>As you can see, this 
function hardcodes a reference to the <TT>TWidget</TT> object
into this call. You therefore can't use this version of the <TT>Widget</TT> object
to get the hierarchy of another object, but only for retrieving its own hierarchy.</P>
<P>To make sure you 
understand how I got started with this new series of files, I
have created a very simple program called Widget1 that contains the <TT>Widgets</TT>
unit and a main program that uses it. The code for the program is available on this
book's CD, and the 
output from the program is shown in Figure 20.1.<BR>
<BR>
<A NAME="Heading11"></A><A HREF="20ebu01.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/20/20ebu01.jpg">FIGURE 20.1.</A><FONT COLOR="#000077">
</FONT><I>The output from the Widget1 program found on the CD that accompanies this
book.</I></P>

<P>The main program contains one procedure that looks like this:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::ShowHierarchyBtnClick(TObject *Sender)

{

  Memo1-&gt;Clear();

  TWidget *W = new TWidget(Memo1);

  Memo1-&gt;Lines = 
W-&gt;GetHierarchy();

  delete W;

}

</FONT></PRE>
<P>If you have questions on how to create this program, go to the <TT>Widget1</TT>
directory and study the example provided there. After you are set up, you can read
the note below and then copy the 
<TT>Widgets.cpp</TT> and <TT>Widgets.h</TT> files
to the <TT>Utils</TT> directory, where <TT>CodeBox</TT> is kept. This file is used
in <TT>Widgets2</TT>, which is described in the next section of this chapter.</P>


<BLOCKQUOTE>
	<P>
<HR>
<FONT 
COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Actually, you might want to be careful
	copying the files. If you are following along by creating copies of the files by
	hand, then go ahead and copy the files. If you are working from my source, be careful
	
that you don't overwrite my copy of the file when you move the file to the <TT>Utils</TT>
	directory. 
<HR>


</BLOCKQUOTE>

<H4><A NAME="Heading13"></A><FONT COLOR="#000077">Working with Widgets</FONT></H4>
<P>In the last section, you got started 
with the <TT>TWidget</TT> object. In the
Widget2 program, shown in Listings 20.1 through 20.5, I add data and methods to the
object so it can serve as the base class for an object that represents some kind
of widget such as a computer chip, a light 
bulb, a book, or whatever. Because the
object could have such a wide range of uses, I keep it very abstract, giving it only
a few traits such as a cost, a creation time, the ability to draw itself, and the
ability to stream itself.

<DL>
	<DT></DT>

</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>You will find that the Widgets module
	gets rewritten several times over the course of the next few chapters. As a result,
	the version of this unit used in the Widget2 
program is stored in the <TT>Widgets2</TT>
	directory on the CD that accompanies this book. There is a second version of this
	unit, stored in the <TT>Utils</TT> subdirectory, that contains the final version
	of <TT>Widgets.cpp</TT>. <BR>
	<BR>
	If 
you are working along with this text, creating your own version of the program,
	it might be best to copy <TT>Widgets.cpp</TT> out to the <TT>Utils</TT> directory
	and update it little by little as the next few chapters unfold. If your efforts get
	
fouled for one reason or another, you can always revert to the versions stored on
	the CD. 
<HR>


</BLOCKQUOTE>

<P><A NAME="Heading15"></A><FONT COLOR="#000077"><B>Listing 20.1. The Main unit for
the Widget2 program.</B></FONT></P>
<PRE><FONT 
COLOR="#0066FF">///////////////////////////////////////

// Main.cpp

// Learning about objects

// Copyright (c) 1997 by Charlie Calvert

//

#include &lt;vcl\vcl.h&gt;

#pragma hdrstop

#include &quot;widgets.h&quot;

#include &quot;Main.h&quot;


#pragma resource &quot;*.dfm&quot;



TForm1 *Form1;

__fastcall TForm1::TForm1(TComponent* Owner)

  : TForm(Owner)

{

}

void __fastcall TForm1::CreateBtnClick(TObject *Sender)

{

  TWidget * Widget= new TWidget(this);

  Widget-&gt;Left = 
ClientWidth / 4 - Widget-&gt;Width / 2;

  Widget-&gt;Top = (ClientHeight / 2) + Widget-&gt;Height;

  Widget-&gt;Parent = this;

  Widget-&gt;Cost = 3.3;

  Widget-&gt;Description = &quot;This is a widget&quot;;

  Widget-&gt;TimeCreated = Now();

  
Memo1-&gt;Lines = Widget-&gt;GetHierarchy();

  Widget-&gt;Show();

  Edit1-&gt;Text = Widget-&gt;TimeCreated;

  WriteWidgetToStream(&quot;Afile.dat&quot;, Widget);

}

void __fastcall TForm1::ReadFromStreamBtnClick(TObject *Sender)

{

  TWidget 
*Widget = ReadWidgetFromStream(&quot;AFile.dat&quot;);

  Widget-&gt;Parent = this;

  Memo1-&gt;Lines = Widget-&gt;GetHierarchy();

  Widget-&gt;Show();

  Edit1-&gt;Text = Widget-&gt;TimeCreated;

}

void __fastcall TForm1::FormResize(TObject 
*Sender)

{

  Memo1-&gt;Left = ClientWidth / 2;

}



</FONT></PRE>
<P><A NAME="Heading16"></A><FONT COLOR="#000077"><B>Listing 20.2. The core of the
Widget2 program is the Widgets unit. The header for that module is shown here.</B></FONT></P>

<PRE><FONT COLOR="#0066FF">///////////////////////////////////////

// Widgets.h

// Learning how to use objects

// Copyright (c) 1997 by Charlie Calvert

//

#ifndef WidgetsH

#define WidgetsH

#include &quot;myobject.h&quot;

class 
__declspec(delphiclass) TWidget;

namespace Widgets

{

  void __fastcall Register();

}

TWidget *ReadWidgetFromStream(AnsiString StreamName);

void WriteWidgetToStream(AnsiString StreamName, TWidget *Widget);

class TWidget: public TCustomControl

{

⌨️ 快捷键说明

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