Object Pascal Free方法的奇怪现象,涉及到面向对象理论,请高手指点。(200分)

  • 主题发起人 ZXW49362727
  • 开始时间
S

savenight

Unregistered / Unconfirmed
GUEST, unregistred user!
mikedeakins: never talk about what you don't even know.
Right,I always do it,And You should do it first when you want to indoctrinate others!
A static method is a early binding method!

Although Object Pascal supports static methods, it doesn’t support static data members
in the manner of C++ or Java. To achieve the same behavior in Object Pascal, you
should use a global variable. You can place the global in the implementation part of
the unit if you want it to behave as private data.
 
S

sadj

Unregistered / Unconfirmed
GUEST, unregistred user!
to Pipi:
[^]你说得对。的确是不一定是nil,所有非法的都是可以的。

to:mikedeakins
delphi的静态方法和没有virtual或者dynamic的方法是一回事,这样我就很不理解一件事情,
那就是delphi的静态方法是可以inherited的,只是不能够被父类的方法“动态(多态?)”
(这里我不知道该如何表达)访问而已,怎么回事?
 
P

Pipi.

Unregistered / Unconfirmed
GUEST, unregistred user!
现在的争论主要是有些人以c++的静态方法理解静态方法
有些人以delphi的静态方法理解静态方法
所以大家谁也不服谁
不过,我还是那句话,不管是什么方法,他都是以自己独特的函数名字link入目标文件的
他都有已知的函数入口
而某些方法,由于程序中未引用,虽然这个类又实例存在,但是他的成员函数甚至在连接的
时候就没有link入exe
 
P

Pipi.

Unregistered / Unconfirmed
GUEST, unregistred user!
inherited和虚函数并没有什么必然联系
比如,在c++里面
class A
{
void func()
//不是virtual
};

class B:public A
{
void func()
//不是virtual
};

我们可以指定 B::func 也可以指定 A::func
inherited func 就相当于在B里面调用 A::func
inherited 只是相当于 父类:: 而已,只是c++里面没有直接限定 父类的快捷方法,必须自己写 A::
 
S

savenight

Unregistered / Unconfirmed
GUEST, unregistred user!
>>这样我就很不理解一件事情,那就是delphi的静态方法是可以inherited的
TTest = class
public
procedure test;
end;

TTestChild=class(TTest)
public
procedure test
//这里把TTest的test方法覆盖了
end;

TTestChild1=class(TTest)
//这里没有实现,所以inherited TTest的方法。
end;
//。。。
var
a:TTestChild;
// a:TTestChild1;
// a:TTest;
begin
a:=TTestChild.Create;
a.test;
a.Free;
end;
 
S

sadj

Unregistered / Unconfirmed
GUEST, unregistred user!
to:pipi
c++的virtual好像是相当于delphi的abstract啊。
to:savenight
是这样的,而且在TTestChild的test方法里面可以inherited,我所奇怪的是这里,你不觉得奇怪吗?
还有delphi的私有方法也可以被继承,也是很奇怪的。
 
S

savenight

Unregistered / Unconfirmed
GUEST, unregistred user!
sadj:我按你的方法在aa.test,点左键+Ctrl怎么出现错误“Error inspecting 'aa.test': expression error”?
调试的时候需要设置什么吗?
 
P

Pipi.

Unregistered / Unconfirmed
GUEST, unregistred user!
c++的virtual就是相当于delphi的virtual
c++的 virtual void func()=0;(纯虚函数) 才相当于delphi的abstract
 
S

sadj

Unregistered / Unconfirmed
GUEST, unregistred user!
to savenight
是这样的,如果test方法是一个virtual的,就会如你所说,如果是个类似free的,就可以了。
我不太清楚那个地址是不是偏移地址?
to Pipi
原来这样啊
 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
看了以上的说法,class method和没有用到内部成员变量的函数的区别是在哪里??

现在看来,class method隐含参数为自身的meta class,而没有用到内部成员变量
的函数则什么隐含参数也没有。因此delphi里才用这种方法,即用了一个非class
method的free.这样保证 象nil.free 或其他什么 v(假设v是一个没有初始化的对象)
调用free不会出错。否则,如果申明成class free的话,v.free还是会保错的.

的确是个有趣的问题,在开发的时候可以试试利用这个语言特性。
 
S

savenight

Unregistered / Unconfirmed
GUEST, unregistred user!
Delphi里和Pipi.分析的C++好像有一点不同,看看下面的例子,数据段也是可以访问的:
type
TTest=class
int:integer;
yn:boolean;
str:string;
obj:tbutton;
public
procedure test;
procedure virtualmethod;virtual;
end;
//。。。
var
a:TTest;
i:Integer;
s:string;
yesno:boolean;
begin
a.Create

a.int:=3;
a.yn :=true;
a.str :='savenight';
a.obj:=button1;
a.test;
// a.virtualmethod
//不能执行
// a.free
//不能执行
a.obj.Caption :='savenight';

i:=a.int;
yesno:=a.yn;
s:=a.str;
caption:=caption+inttostr(a.int)+inttostr(i)+s;

end;
 
P

Pipi.

Unregistered / Unconfirmed
GUEST, unregistred user!
darkiss你说的啥呀,全搞错了
class method就是c++的static成员函数,他没有隐含的参数,他就是一个真正的全局函数
他写在class里面纯粹是为了美观,表示他和这个class很有关系
而没有用到内部成员变量的函数则和其他的普通的成岩函数是一样的,仅仅是
他调用的时候 obj.method ,这个obj是什么都不会出错而已,而且他是隐含了一个参数的,
就是self(就是obj)指针,只是函数里面没有用到self,所以即使obj不对也不出错而已
 
P

Pipi.

Unregistered / Unconfirmed
GUEST, unregistred user!
savenight我不知道你想证明什么,不过,不管怎么样,
delphi和c++只在那个static定义不同
static<->class method
普通函数<->static method
而已,原理是一样的,否则bcb也不能直接使用vcl,而且在同版本下的bcb和delphi可以使用同一个实例数据
 
S

savenight

Unregistered / Unconfirmed
GUEST, unregistred user!
Pipi.:你说的数据具体指的是什么?
 
S

savenight

Unregistered / Unconfirmed
GUEST, unregistred user!
type
TTest=class
int:integer
//这算数据吗?
 
D

darkiss

Unregistered / Unconfirmed
GUEST, unregistred user!
to pipi

对于普通的成员函数,的确有个隐含参数,是self,即对象本身。这个self是个TObject

对于class method,也有一个隐含参数,也用self表示,不过表示类本身。这个self是个TClass

那么,假设free是一个class method,那么 v.free 实际上(这里v是指一个invalid object)
的调用是通过v来获取v的类,假设是t,然后调用t->free。因为v是非法的,所以根本不能查找到
t,而且查找t的过程就造成了AV错误。相反,如果free用普通的成员函数,只要不用到成员变量,
就不会出现这种错误。这里用self <> nil就是这个意思。

还有就是这个成员函数必须是static_bind的,不能用virtual,dynamic等修饰。否则,编译器不会
在编译时刻就确定该函数的调用地址,只要一动态查找,因为对象非法,还是会出AV错误。

假设free是一个动态成员函数,那么是先确定free的函数地址,才进行self<>nil的判断,而确定
free的过程就会造成AV.
 
P

Pipi.

Unregistered / Unconfirmed
GUEST, unregistred user!
哦,对,我搞错了
delphi的class method 不等于 c++的static member
delphi的class method隐含传入了类信息的指针
c++的static member是纯正的全局函数,没有任何隐含的参数。所以它可以作为windows的回调函数使用
看来我把c++硬往delphi头上套还不是全部有效的
 

吴明星

Unregistered / Unconfirmed
GUEST, unregistred user!
你们讲了很多,我也明白了一点,但还是理不清头绪。能不能请高手总结一下这个问题呀?
 
L

lance2000

Unregistered / Unconfirmed
GUEST, unregistred user!
确实有两个self,我也是前两天才注意到.大家有没有发现,构造函数也可以被声明
为虚函数,可是这个构造函数是有类来引用,而非对象,也就是说即使是虚函数也不
能实现多态,是不是有点矛盾啊?
 
顶部