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

📄 ch19.htm

📁 好书《C++ Builder高级编程技术》
💻 HTM
📖 第 1 页 / 共 5 页
字号:

  private:

    virtual TObject* __fastcall NewInstance(TClass cls);

  public:

    virtual void __fastcall FreeInstance();

    virtual __fastcall ~TObject() {}

};

</FONT></PRE>
<P>You can find the entire 
implementation of <TT>TObject</TT> in the Object Pascal
<TT>System.pas</TT> unit that ships with BCB. Much of it is actually in assembler,
but the source is there if you want to study it. You should, of course, also examine
the declaration for 
<TT>TObject</TT> in <TT>SysDefs.h</TT>. The calls in <TT>SysDefs.h</TT>,
however, ultimately resolve into calls to the Pascal implementation in <TT>System.pas</TT>.
I should perhaps add that the <TT>TObject</TT> declaration in <TT>SysDefs.h</TT>
is 
very hard to understand, but I promise you that it does end up resolving into
calls that access the <TT>System.pas</TT> version of <TT>TObject</TT>.

<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> 
</B>Although I have mentioned this subject
	before, it's probably once again time to stress the importance of viewing the Pascal
	source code to the VCL. Your version of BCB might or might not ship with the source,
	but if you don't have it and can 
possibly afford to buy it, you should think seriously
	about obtaining it. You should peruse the <TT>BCB\Include\VCL</TT> subdirectory that
	contains the header files for the imported VCL Pascal units. These files provide
	the interface for key BCB 
units. They are not as good as having the source, but they
	are very valuable. I refer to both the header files and the Pascal source continuously.
	
<HR>


</BLOCKQUOTE>

<P>You can see that <TT>TObject</TT> has a few basic functions declared right 
at
the top:</P>
<PRE><FONT COLOR="#0066FF">__fastcall TObject() {}

__fastcall Free();

virtual __fastcall ~TObject() {}

</FONT></PRE>
<P>The point to grasp here is that <TT>TMyObject</TT> has a destructor and <TT>Free</TT>
method because it inherits 
them from <TT>TObject</TT>.</P>
<P>To understand this point, you can add a line of code to the nascent OBJECT1 program:</P>
<PRE><FONT COLOR="#0066FF">#include &lt;conio.h&gt;

#include &lt;stdio.h&gt;

int main(void)

{

  TMyObject *MyObject = new 
TMyObject;

  AnsiString S = MyObject-&gt;ClassName();

  printf(S.c_str());

  delete MyObject;

  getch();

  return 0;

}

</FONT></PRE>
<P>This code enables the object to write its name to the screen. The output from
this program is a single 
string:</P>
<PRE><FONT COLOR="#0066FF">TMyObject

</FONT></PRE>
<P>When you run the program, this string might flash by too quickly for leisurely
perusal. To remedy the situation, add a <TT>getch()</TT> at the very end of the code,
right before 
the<TT> return</TT> statement. To end this program, press Enter. (That's
the way it used to be done back in the DOS world.)</P>
<P>If you want to, you can even get this object to say its parent's name:</P>
<PRE><FONT COLOR="#0066FF">int main(void)

{

  
TMyObject *MyObject = new TMyObject;

  printf(Format(&quot;ClassName: %s\nParent's ClassName: %s&quot;,

    OPENARRAY(TVarRec, (

      MyObject-&gt;ClassName(),

      MyObject-&gt;ClassParent()-&gt;ClassName()))).c_str());

  

  delete MyObject;

  
getch();

  return 0;

}

</FONT></PRE>
<P>The output from this code is the following:</P>
<PRE><FONT COLOR="#0066FF">ClassName: TMyObject

Parent's ClassName: TObject

</FONT></PRE>
<P>The point, of course, is that <TT>TMyObject</TT> inherits quite a 
bit of functionality
from its parent, and, as a result, it has numerous capabilities that might not be
obvious from merely viewing its declaration.</P>
<P>The ability to trace an object's ancestry is relatively appealing, so it might
be nice to add it 
to <TT>TMyObject</TT> as a method:</P>
<PRE><FONT COLOR="#0066FF">#include &lt;vcl/vcl.h&gt;

#include &lt;stdio.h&gt;

#include &lt;conio.h&gt;

#include &quot;classrefs.h&quot;

USEUNIT(&quot;ClassRefs.cpp&quot;);



class TMyObject : public TObject


{

public:

  TMyObject() : TObject()  {}

  void PrintString(AnsiString S);

  void ShowHierarchy();

};



void TMyObject::PrintString(AnsiString S)

{

  printf(&quot;%s\n&quot;, S.c_str());

}



void TMyObject::ShowHierarchy()

{

  TClass 
AClass;



  AnsiString AClassName = AnsiString(ClassName()).c_str();

  PrintString(AClassName);

  AClass = ClassParent();

  while (AClass)

  {

    AClassName = AnsiString(AClass-&gt;ClassName());

    PrintString(AClassName);

    AClass = 
AClass-&gt;ClassParent();

  }

}



int main(void)

{

  ShowClassReferences();

  TMyObject *MyObject = new TMyObject;

  MyObject-&gt;ShowHierarchy();

delete MyObject;

  getch();

  return 0;

}

</FONT></PRE>
<P>This version of the OBJECT1 
program includes two methods, listed in the <TT>TMyObject</TT>
class declaration:</P>
<PRE><FONT COLOR="#0066FF">class TMyObject : public TObject

{

public:

  TMyObject() : TObject()  {}

  void PrintString(AnsiString S);

  void ShowHierarchy();


};

</FONT></PRE>
<P>Take a look at the implementation for <TT>ShowHierarchy</TT>. Perhaps the first
thing you notice in it is the class reference in the first line, which uses the <TT>TClass</TT>
type.</P>
<P>The type <TT>TClass</TT> is an object 
reference and is declared in <TT>Sysdefs.h</TT>
as follows:</P>
<PRE><FONT COLOR="#0066FF">typedef TMetaClass* TClass;

</FONT></PRE>
<P>Because <TT>ClassParent</TT> returns a variable of type <TT>TClass</TT>, it is
obviously what needs to be used 
here.

<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>An object reference is a special
	metaclass that can be assigned to an object. Here is a unit that shows some legal
	uses of an object 
reference:</P>
	<PRE><FONT COLOR="#0066FF">///////////////////////////////////////

// ClassRefs.cpp

// Object1

// copyright (c) 1997 by Charlie Calvert

//

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

#include &lt;forms.hpp&gt;

#pragma hdrstop

#include 
&quot;ClassRefs.h&quot;

TClass AClass;

  class TDescendant: public TObject

  {

  public:

    TDescendant(): TObject() {}

</FONT></PRE>

</BLOCKQUOTE>


<DL>
	<DL>
		<DT><FONT COLOR="#0066FF"></FONT></DT>
	</DL>
</DL>



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

  };

void ShowClassReferences()

{

  printf(&quot;** Start object references **\n&quot;);

  AClass = __classid(TObject);

  printf(&quot;%s\n&quot;, AnsiString(AClass-&gt;ClassName()).c_str());

  AClass = __classid(TDescendant);

  
printf(&quot;%s\n&quot;, AnsiString(AClass-&gt;ClassName()).c_str());

  AClass = __classid(TForm);

  printf(&quot;%s\n&quot;, AnsiString(AClass-&gt;ClassName()).c_str());

  printf(&quot;** End object references **\n\n&quot;);

}</FONT></PRE>
	
<P>Notice that you do not have to create an object before you can use it with an
	<TT>object reference</TT>. In general, you can call any of the static methods of
	<TT>TObject</TT> with a class reference. <BR>
	<BR>
	You cannot use an object reference 
to refer to a field that belongs only to the child
	of the <TT>object reference</TT> type. For instance, this code does not compile because
	<TT>Caption</TT> is not a property of <TT>TObject</TT>:</P>
	<PRE><FONT COLOR="#0066FF">ObjectRef =  
__classid(TForm)

ObjectRef.Caption := `Sam';

WriteLn(ObjectRef.Caption);</FONT></PRE>
	<P>You will find a version of the <TT>CLSREF</TT> unit in the same subdirectory as
	OBJECT1. You can use the Project Manager to add this file to the project, and 
you
	can then call it in the second line of the body of the OBJECT1 program. However,
	you should not leave this unit as part of the project, because it will muddy the
	view of the object hierarchy that you get in the Browser. <BR>
	<BR>
	There are 
not that many times in which you need to use an object reference in day-to-day
	programming. If you are not totally clear on what they do, you can probably afford
	to skip the subject. If you really want to know more, you should examine 
<TT>Sysdefs.h</TT>;
	recognize that the <TT>TMetaClass</TT> you see there is the C++ way of creating a
	feature that exists in the VCL. The reason the VCL supports this feature is that
	it needs fairly extensive Run Time Type Information (RTTI) in 
order to run, and it
	gets a good portion of that information from the methods in <TT>TObject</TT> that
	are part of <TT>TMetaClass</TT> and are in turn used in an object reference. 
<HR>


</BLOCKQUOTE>

<P>When you get past the object reference, the 
remaining portions of the <TT>ShowHierarchy</TT>
method are fairly straightforward:</P>
<PRE><FONT COLOR="#0066FF">void TMyObject::ShowHierarchy()

{

  TClass AClass;

  AnsiString AClassName = AnsiString(ClassName()).c_str();

  
PrintString(AClassName);

⌨️ 快捷键说明

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