关于类指针变量的问题 ( 积分: 100 )

  • 主题发起人 主题发起人 brightsea_pan
  • 开始时间 开始时间
B

brightsea_pan

Unregistered / Unconfirmed
GUEST, unregistred user!
当一个类指针变量(或者是类引用)被声明时,其值为inaccessible(不可访问的?还是应该怎么翻译好),具体是什么意思?类指针变量指向一个具体的对象后,再调用free方法,其值变为(),一个括号,也不知道是什么意思?如果在c中,指针变量被声明时其值是NULL,调用DELETE方法释放其指向的对象时,其值由变为NULL,这样就很好理解了。但DELPHI中就不是了,比如a:TObject
不执行任何操作 ,a = nil 这个逻辑式是false。执行下两条语句后

(a := TObject.Create
a.Free;)后a = nil 这个逻辑式还是false。

请高手指教。

 
当一个类指针变量(或者是类引用)被声明时,其值为inaccessible(不可访问的?还是应该怎么翻译好),具体是什么意思?类指针变量指向一个具体的对象后,再调用free方法,其值变为(),一个括号,也不知道是什么意思?如果在c中,指针变量被声明时其值是NULL,调用DELETE方法释放其指向的对象时,其值由变为NULL,这样就很好理解了。但DELPHI中就不是了,比如a:TObject
不执行任何操作 ,a = nil 这个逻辑式是false。执行下两条语句后

(a := TObject.Create
a.Free;)后a = nil 这个逻辑式还是false。

请高手指教。

 
var
Form1: TForm1;
pp:PPoint;

建议先看书
 
在delphi中,把对象Free并不能将其设置为nil的。
如果同时完成可以使用函数FreeAndNil(AObject);
 
现在我想解决的问题是:一个类引用到底有没有指向一个具体的对象。
或者说我现在想用这么一个析构函数:假如类引用没有指向一个具体的对象,则不执行释放对象的操作,假如类引用指向一个具体的对象,则执行释放对象的操作。
各位朋友顺便推荐几本好书:)
 
TClass=class of TObject;

TClass这个才叫类引用.

你的类指针变量,叫类的实例应该更好。
在DELPHI中。

var A:TObject;

这个A并不等同与C++中的定义。在DELPHI中尚未为A分配内存,所以它是不可访问。
只有调用Create后才可以使用。才可以调用FREE。

“我现在想用这么一个析构函数:假如类引用没有指向一个具体的对象,则不执行释放对象的操作,假如类引用指向一个具体的对象,则执行释放对象的操作。”

如果具体的对象不存在又如何调用它的析构函数呢?

 
对象引用(指针),他是在栈中分配空间的,其初始化和销毁由Delphi编译器自动进行。
对象实例,他是在堆中分配空间的,其初始化和销毁由开发者完成(具备自动生存期管理的接口型对象例外)
procedure UseSomeObject;
var
AObj : TObject;
begin
AObj := TObject.Create;
end;
在调用TObject构造器之前的AObj,他是栈的一个指针型变量,他不等于nil,他的值是在创建AObj指针之前栈里面的内容,也许他凑巧指向了一个真正的对象实例,也许他指向的是无效内存空间,这个是无法预测的。调用构造器后,他获得了一个真正的对象实例在内存中的地址。
UseSomeObject的调用完成之后,堆中的对象实例仍然存在,编译器开始恢复栈空间,此时AObj指针的值被之前栈的内容所覆盖而丢失。这也就是所谓的内存泄露,因为将来不可能用这个对象引用释放内存堆中的实例。
如果修改为这个样式:
procedure UseSomeObject(CreateMode : boolean);
var
AObj : TObject;
begin
if CreateMode then AObj := TObject.Create Else AObj.Free;
end;
唯一可以确定的是,堆中产生的对象实例永远不会被销毁,比较大的一种可能性是抛出AV错误,如果凑巧的情况下,即存放AObj指针的栈的内容刚好是一个真正的对象,那么该对象会被正确销毁。
另外一个有趣的例子:
procedure UseSomeObject(CreateMode : boolean);
{$J+}
const AObj : TObject = nil;
{$J-}
begin
if CreateMode then AObj := TObject.Create Else AObj.Free;
end;
只要遵循正确的调用顺序,这段代码可以很正确的创建对象和销毁对象。原因就在于const类型的常量,编译器会开辟特殊的空间保存他的值,入栈/出栈的动作并不会使他的值有所变动。
最后一点是,调用对象的析构器并不能将对象指针置为nil,因此在一般的情况下,销毁对象之后紧接着将指针置为nil是个很好的习惯,自然也可以直接调用FreeAndNil(早期靠代码行数收费的开发者都很喜欢分两步,笑)。
至于最后的问题,如何确定一个对象指针是否指向了一个对象实例。如果你正确的创建和销毁对象,那么一般是不需要考虑的。如果你实在是想追求背后的真相,我记得Aimingoo有一篇关于这个问题的研究文章相当不错,你可以找来看看。

最后一个例子无法保证可以按照我的意图在你的机子上正确工作。放个Button在空白窗体,并且单击Button,是不是button莫名其妙的消失了?呵呵
procedure Func(Index : integer);
var BObj : TObject;
begin
if Index = 1 then BObj := TObject.Create
else if Index =2 then BObj.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Func(2);
end;
 
现在我想解决的问题是:一个类引用到底有没有指向一个具体的对象。
或者说我现在想用这么一个析构函数:假如类引用没有指向一个具体的对象,则不执行释放对象的操作,假如类引用指向一个具体的对象,则执行释放对象的操作。
各位朋友顺便推荐几本好书:)

var A:TObject;
上述语句中对象A值为空,其实质只分配了一用于指向对象实例的空间。
当执行A:=TObject.Create;后A才正式指向具体的实例。
当执行A.Free;后A所指向实例被释放,但A中值并不为空。
你要让A值为空可以加上A:=nil;语句,或者使用FreeAndNil(AObject);语句。
判断一个对象有没有被分配可以用if assigned(AObject) then,也可以用if a=nil then 语句。
说明:要在析构语句中执行对自身对象的判断,以及执行对引用自身对象的变量赋空,两者在delphi中是不可能的。前者属于逻辑错误,因为既然连自身都不存了,本身就不能操作自身函数。后者因为在析构时pascel语句并未曾向析构函数传递引用变量的地址,因些在析构函数中无法实现对引用变量赋空的操作。


 
谢谢各位了:)
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
913
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部