类创建的问题 ( 积分: 100 )

  • 主题发起人 主题发起人 小飞龙
  • 开始时间 开始时间

小飞龙

Unregistered / Unconfirmed
GUEST, unregistred user!
我有一个父类-base,他有2个子类A,B,
我定义一个父类并创建一个实例.
A,B里面都有一个自己的方法,我现在分别强制转换创建这个实例为A,或者B,然后调用子类的方法,分别看到对应之类方法的提示.我有点不明白,实例创建的是父类.是没有子类的方法的.强制转换的时候到底系统做了什么事情.为什么2个子类的方法都可以调用.
谁知道原理给我讲讲,谢谢了!
 
原理倒是说不上,一般做法就是父类声明,子类创建,可以实现多态。如果父类声明,父类创建,是不能通过强制转换并调用子类方法的,按我的理解,创建的时候真正分配内存
比如。
TBase = class
procedure ShowInfo;
end;

TClassA = class(TBase)
procedure show;
end;

TClassB = class(TBase)
procedure show;
end;


var
Base: TBase;
begin
Base := TClassA.Create;
(Base as TClassA).show;
end;
这是可以的

var
Base: TBase;
begin
Base := tBase.Create;
(Base as TClassA).show;// 这样就报错了,

也就是说vmt里面没有子类的方法
 
不要用as,我上用
TClassA(Base).show
这样的,这样可以通过.
这样是否需要重新分配实例内存?
 
你在子类中声明的子类特有方法一定是一个基本上啥也没干的方法。如果你在子类中的方法中访问子类特有的数据,肯定会出问题的。
其实,你强制转换的结果仅仅是放大了一个指针的作用域而已。至于会不会出错误,那取决于放大之后,被方大的部分是否有合法的数据。
(比如:P: PChar,P是一个PChar类型的指针,他能访问的仅仅是一字节的内存,如果进行如下操作n := PInteger(P)^,那么,你可能会取出一个整数。也就是说,你的强制转换放大了P的作用域,使P由原来的只能访问一字节的内存变成了能访问4字节的内存)
aObj: TObject
aObj本身是一个指针,如果TButton(AObj),其实就是放大了AObj这个指针的访问范围。
为什么你强制转换之后可以访问到子类的特有方法呢?
那是因为普通方法在编译期就已经确定了方法的入口地址,Delphi在编译你的源代码的时候,遇到访问普通方法的语句,会直接将其转换成 Call [方法地址] 的形式
至于这个 方法地址 是什么,那取决于你给的类类型,比如TButton(AObj).Click,那取的地址就是TButton的Click函数的地址。注意,之说的仅仅是一般方法(即非虚、非动态、非消息方法,呵呵)。
 
如果你通过强制转换的方式访问的是类中的一般方法,比如TButton(AObj).Click;
获得 方法地址 只和你强制转换的类型有关(即和 TButton 有关,而和AObj无关)
不信你可以试试
TYouObj(0).YouFunc
TYouObj(100).YouFunc
TYouObj(123545).YouFunc
都好使
 
谢谢放飞,确实如你说的,一般函数才可以.
不过我试了一下,在子类定义自己的成员变量,然后在对应的一般函数里面赋值显示,很正常
 
不报错不代表没有错误,如果那块内存恰好被分配出去了,那么你写那块内存就没有问题。
你可以在你子类的方法中,使用 self.classname 看看,你就知道了
 
呵呵,不错的讨论
 
接受答案了.
 
后退
顶部