[讨论]关于class

gogogo 2005-04-14 11:04:48
我搞Delphi也有一段时间了,只是有两个地方一直搞不懂:
一、class of 关键词
  1、这个东西本质上到底是什么?
  2、这个东西主要作用是什么,主要用于什么地方?
  3、经过编译器编译后在内存中如何表示(这个好像比较难,可以不回答)?
二、class 方法
  就是类似
  class function Supports(Operation: string): Boolean; virtual;
  1、这个东西本质上到底是什么?
  2、这个东西主要作用是什么,主要用于什么领域?

欢迎大家讨论讲解,最好有例子说明。

声明:由于问的问题个人感觉比较难,又根据以往的经验,难的问题一般每人能回答出来,给的分都给了垃圾人(给分系统的大bug),所以本次不多给分,就20分垫底,作为散分之用,有真正好的回答和讨论,我会单独再给分,50分打底,大家多支持阿。
...全文
131 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
梅青松 2005-04-14
  • 打赏
  • 举报
回复
相当于静态类
何鲁青 2005-04-14
  • 打赏
  • 举报
回复
一、在delphi中有一种特殊的class,类引用,class of 就是用于定义这种类型的类的,这种类的特殊之处在于,通过他的构造函数构造出的不是对象,而是类;
TMyClass = class
public class procedure Show();
end;
TMyClassClass = class of TMyClass;

var MyClass : TMyClassClass;
MyObj : TMyClass;
begin MyObj := MyClass.Create();
MyClass.Show();
MyObj.Free();
end;
//////还有很多,我可能说不清楚,推荐你一本书《delphi高手突破》第二章有详细的讲解
我有电子版的,如果要的话,可以给你一份....
beyondtkl 2005-04-14
  • 打赏
  • 举报
回复
inside VCL ...

class of:
reference of class , but default ref is object's ref, here, look class as object
then it has the same poly-***(多態),

here code in vcl Controls.pas

TWinControlClass = class of TWinControl; // 1.

FFloatingDockSiteClass: TWinControlClass; // 2

function TControl.CreateFloatingDockSite(Bounds: TRect): TWinControl; // 3
begin
Result := nil;
if (FloatingDockSiteClass <> nil) and
(FloatingDockSiteClass <> TWinControlClass(ClassType)) then
begin
Result := FloatingDockSiteClass.Create(Application); // 4.
// pls look 4,
// FloatingDockSiteClass是類的引用 我們不知道它究竟是指向哪個類,就是編譯時期不能確定,只有到運行時才能確定,稱為動態綁定,這裡就 自動去調用FloatingDockSiteClass所指向類的構造函數,比如 如果是TForm那就調用TForm.Create,如果是TWincontrol那就是調用TWincontrol.Create,(這裡的例子不一定准確,只是為了說明) 當然 要求你後面的函數是virtual or dyanmic的才能支持 多態。
end;
end;

class method:
類的對象有一個Self指針,默認的member method call by Self, but class method can call by the class name, 本質 都是一個地址, 只不過這個地址得到得方法不一樣而已。。

還是要看 李維得 inside vcl 與 lippman 得 inside the C++ Object Model有的一拼。
linzhengqun 2005-04-14
  • 打赏
  • 举报
回复
另外:关于:
二、class 方法
  就是类似
  class function Supports(Operation: string): Boolean; virtual;
  1、这个东西本质上到底是什么?
  2、这个东西主要作用是什么,主要用于什么领域?

类方法当然就是类的方法,可以被类直接调用TMyClass.Func
你看一下TObject的类方法,就大概能明白了。
linzhengqun 2005-04-14
  • 打赏
  • 举报
回复
这是我之前写的一篇小札记,可以一看,
不过更推荐去看一个《Delphi原子世界》网上可以找到:


好久没有来了
读Delphi原子世界中一段的札记:
先看一段话,再根据这段文章用一例子来测试:
对象就是一个带柄的南瓜。南瓜柄就是对象的指针,南瓜就是对象的数据体。确切地说,DELPHI中的对象是一个指针,这个指针指向该对象在内存中所占据的一块空间。我们将对象指针指向的内存空间称为对象空间。对象空间的头4个字节是指向该对象直属类的虚方法地址表(VMT – Vritual Method Table)。接下来的空间就是存储对象本身成员数据的空间,并按从该对象最原始祖先类的数据成员到该对象具体类的数据成员的总顺序,和每一级类中定义数据成员的排列顺序存储。
我们声明一个类:
TMyclass=class
mem1:integer;
mem2:string;
mem3:integer;
end;
再声明一个类变量
Myclass:TMyclass;
然后写一段代码:
myclass:=Tmyclass.Create;
myclass.mem1:=21;
myclass.mem2:='i find you by this way!';
Edit1.Text:=InttoStr(PInteger(Integer(myclass)+4)^);
Edit2.Text:=PString(Integer(myclass)+8)^;
myclass.Free;
运行结果,Edit1显示21,Edit2显示i find you by this way!
根据上面的说法,解释如下:myclass实际上是一个指向对象内存空间的指针,所以Integer(myclass)就是对象内存空间的首地址,首地址的4个字节保存对象所属类的VMT,而过了这4个字节的后面4个字节,保存对象的成员Mem1,再过4个字节,保存对象的成员Mem2。那么,Integer(myclass)+4就是成员Mem1的地址啦,而另一个成员Mem2当然是保存在地址为Integer(myclass)+8的内存当中啦。我们将地址为Integer(myclass)+4强制变成一个指针,再得到指针所指向的内存块的值,也即是如下形式:PInteger(Integer(myclass)+4)^当然就是第一个成员的值啦。而同样道理:PString(Integer(myclass)+8)^当然是第二个成员的值啦。

而对象内存空间的首4个字节是类VMT的地址,那么我们再看另一段代码,以得到该对象所属类的一些信息, 在这之前,要求对VMT的结构有一些了解:
Var ClassHead:Integer;
begin
myclass:=Tmyclass.Create;
ClassHead:=PInteger(myclass)^+vmtClassName;
Edit1.Text:= PShortString(Pointer(ClassHead)^)^;
Edit2.Text:=InttoStr(PInteger(Integer(myclass)+4)^);
myclass.Free;
end;
PInteger(myclass)^取得对象首4个字节的值,也即是VMT的地址,而这一句ClassHead:=PInteger(myclass)^+vmtClassName;则是VMT首地址向负方向移负44个字节的地址,该地址的内存中存放了一个指向类名的指针。所以我们如果写了这一句Pointer(ClassHead)^,则是取得了该地址的内存块的值了(也即是取得指向类名短字符串的指针),该值实际上也是一个地址,指向类名短字符串的地址,那么把它强制转一个ShortString的指针,再取指针的值,当然就取得了类名了。

上面是有关对象的内存结构,下面我们来说类的内存结构了,其实上面已经很清楚了,类其实应该是一个VMT的首地址,注意和对象的区别,对象是指向对象内存空间,再由内存空间的首4个字节的值指向VMT的地址。也就是说一个类的多个对象都共享一张VMT。
再看下面的一段话:
每一个类都有对应的一张VMT,类的VMT保存从该类的原始祖先类派生到该类的所有类的虚方法的过程地址。在VMT的负方向偏移有76个字节的数据信息,它们是类的基本数据结构。而VMT是存储我们自己为类定义的虚方法地址的地方,它只是类数据结的构扩展部分。VMT前的76个字节的数据结构是DELPHI内定的,与编译器相关的,并且在将来的DELPHI版本中有可能被改变。
在DELPHI中我们用TObject、TComponent等等标识符表示类,它们在DELPHI的内部实现为各自的VMT数据。而用class of保留字定义的类的类型,实际就是指向相关VMT数据的指针。
当一个对象产生时,系统会为该对象分配一块内存空间,并将该对象与相关的类联系起来。于是,在为对象分配的数据空间中的头4个字节,就成为指向类VMT数据的指针。
我们再来看一段代码:
Edit1.Text:=InttoStr(PInteger(Integer(Tmyclass)+vmtInstanceSize)^);
Edit2.Text:=PShortString(Pointer(Integer(TMyclass)+vmtClassName)^)^;
Integer(Tmyclass)取得了VMT的首地址的,再向负方向移动vmtInstanceSize即-40个字节,即到了保存对象尺寸的内存块的地址,将该地址转为一个指针,再得到指针指向内存块的值,即是类的对象的尺寸了:
PInteger(Integer(Tmyclass)+vmtInstanceSize)^
而另一个也不必过多解释了。
文中有一句话:而用class of保留字定义的类的类型,实际就是指向相关VMT数据的指针。如果它是指向VMT的指针,那么应该也可以通过对他操作而得到VMT的一些数据。先声明一个类引用:TMYCC=class of TMyClass;再定义一个该引用的变量:MYCC:TMyCC;
现在作如下测试:
Edit1.Text:=PShortString(Pointer(Integer(MyCC)+vmtClassName)^)^;
却发现违法访问。
后来一想,我们平常用类引用,多用于增加对象创建的灵活性,比如用一个类引用作为方法的参数,则可以将与类引用相对应的类或它的子类传递进方法,然后由方法的类引用参数来创建对应的对象。
那么类引用应该是要被赋值之后才有意义了。则我们写如下的代码看看:
MyCC:=TMyClass;
Edit1.Text:=PShortString(Pointer(Integer(MyCC)+vmtClassName)^)^;
运行结果果然就得到了类的名字:TMyClass
我们再进一步,声明一个TMyClass的子类:
TMySubClass=class(TmyClass);
然后将代码改为如下:
MyCC:=TmySubClass;
Edit1.Text:=PShortString(Pointer(Integer(MyCC)+vmtClassName)^)^;
运行结果是子类的名字:TMySubClass。

一切都清楚了,其实说类引用是一个指向VMT的指针并不准确,类才是一个指向VMT的指针,而类引用的变量也是一个指针,开始时并没有指向VMT,所以一开始必须被赋值,一旦被赋予了一个类(也即指向VMT的指针)则该类引用变量就指向了该类的VMT了。
gogogo 2005-04-14
  • 打赏
  • 举报
回复
好像有点意思了,希望大家积极发表意见
yeeyee 2005-04-14
  • 打赏
  • 举报
回复
一、class of 关键词
  1、这个东西本质上到底是什么?
  2、这个东西主要作用是什么,主要用于什么地方?
  3、经过编译器编译后在内存中如何表示(这个好像比较难,可以不回答)?
二、class 方法
  就是类似
  class function Supports(Operation: string): Boolean; virtual;
  1、这个东西本质上到底是什么?
  2、这个东西主要作用是什么,主要用于什么领域?
一、
1、类的类,也就是类的引用,这是高于 C++++ 的地方。
2、我知道一点,动态创建控件,用到设计模式中的 Factory 。
3、你自己说了,不会答。
二、
1、类的方法,类和对象可以调用 ,相当于 Edti:=TEdit.Create(Self).
TEdit 就调用了类的方法,
2、主要用于取得类的信息,比如类名程,占用的内存大小。

建议:
看看 刘艺的 Delphi 面向对象
李维 Inside VCL

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧