要得到一个类实例的地址为什么用@self会出错(200分)

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

slfeng

Unregistered / Unconfirmed
GUEST, unregistred user!
我需要在一个类实例里面取得它的地址
开始我用@self
程序编译无问题
最后我发现这样取得的指针不一定正确
然后开始找原因
结果,我发现在一个类实例里面的不同函数里面设置断点,取得的@self都是不同的。
请问这是什么原因。
我如果需要在一个类实例的函数(过程)内部取得该实例的地址,可以如何做?
谢谢
 
应该 self 就是了,对象名本来就是实例地址,你再对它取地址,怎么会取得对?
 
开始我也这么想
我写个代码大概意思

Type
TPGraph = ^ TGraph;
class GraphNode
public
Parent : TPGraph;
end;

class Graph
// .....
GraphNodes: Array of GraphNode;
end;

//.....
//.....
procedure TGraph.AddGraphNode(var Source: TGraphNode);
begin
// ...
GraphNodes[ FGraphNodeNum - 1 ].Parent := self ;
// 编译器提示出错
//...
end;
—————————————————————————————————————————
[Error] GraphUnit.pas(1130): Incompatible types: 'TGraph' and 'TPGraph'

然后我才把
GraphNodes[ FGraphNodeNum - 1 ].Parent := self ;
// 编译器提示出错
改成了
GraphNodes[ FGraphNodeNum - 1 ].Parent := @self ;
// 编译器提示通过
然后编译通过
self这玩意天天用,但是从来没有想那么细节,不知道是什么原因
谁要是知道,向您请教一下
 
Type
TPGraph = ^ TGraph;
class GraphNode
public
Parent : TPGraph;
end;

为什么要这样定义?这样不行吗?
Type
class GraphNode
public
Parent : TGraph;
end;

照你的定义,Parent应该是个指针,用self赋值当然会提示类型不对,改成这样应该不错:
procedure TGraph.AddGraphNode(var Source: TGraphNode);
begin
// ...
GraphNodes[ FGraphNodeNum - 1 ].Parent := TPGraph(self) ;

//...
end;

 
Type
class GraphNode
public
Parent : TGraph;
end;
我觉得还是定义成比较好,你定义一个指针去指向一个对象和直接定义一个对象,对系统
来说都是一样的,何必要绕个圈子?
 
这个问题值得研究。
 
试试LongInt(self)是不是每次一样。
 
我重新查了
1>
赋值表达式
GraphNodes[ FGraphNodeNum - 1 ].Parent := @self
的形式是正确地
2> 在一个Class实例的几个不同函数内部用@self取得的指针好像不一定完全一致。
在这个Class实例的外部用 @实例标识符 取得的指针地址也不一样
现在的问题就出在 问题 2上面。
顺便说一下 Longing( self ) 或者 Longint( @self )的类型转换编译器都通不过编译。
 
GraphNodes[ FGraphNodeNum - 1 ].Parent := self
改为GraphNodes[ FGraphNodeNum - 1 ].Parent := Pointer(self)呢?
 
To shenloqi
呵呵,但是,编译器告诉我self本来不是一个指针,就算我把它转换成指针也是不正确的
 
为什么非要用指针?
Type
class GraphNode
public
Parent : TGraph;
end;

class Graph
// .....
GraphNodes: Array of GraphNode;
end;

//.....
//.....
procedure TGraph.AddGraphNode(var Source: TGraphNode);
begin
// ...
GraphNodes[ FGraphNodeNum - 1 ].Parent := self ;
// 编译器提示出错
//...
end;
 
呵呵,我只需要也必须只有一个Graph的实例,所以用了指针。
 
问题解决了
方案如下
Type
TPGraph = ^ TGraph;
TGraph = class(TObject)
public
pSafePoint : TPGraph;
// ...
end;
//...
//...
//...
var Graph : TGraph;
begin
Graph := TGraph.Create();
Graph.pSafePoint := @Graph;
//...
//...以后Graph内部要使用自己的指针可以使用pSafePoint
//...使用@Self取得的指针在Graph内部不同的函数中不一定相同
//...且都不正确
end;

// 问题是解决了
// 但是我还是不知道为什么@self取得的指针是不安全的?
// 我想向高手请教一下再结束问题
 
為了這個--只需要也必须只有一个Graph的实例,你就用指針?
self 是一個全局變量,它的地址是固定的,無論是在哪個實例中
而它的值是變化的,等於當前實例的地址.
 
"试试LongInt(self)是不是每次一样。"
var
a,b:Longint;
A区
a:=LongInt(self);
B区
b=LongInt(self);
结果
a=b
说明self在哪里都是一样的。
@self是取self存放的地方,self存放的地方不等于类实例存放的地方。
self是一个指向类实例存放的地方的变量,所以每次LongInt(self);返回的值都是一样的,因为
这里不是取地址,是转换成一个你能看明的值。
 
@self可以用呀
我就用过
 
其实本身TGraph的实例就是一个指针,所以Self也是一个指针,对指针取地址,
其实得到的是指针的地址,即是所谓指向指针的指针,
>>>>>>>>>>>>>> 呵呵,我只需要也必须只有一个Graph的实例,所以用了指针。
为什么"所以用了指针?",用指针就可以只需要也必须只有一个Graph的实例吗?
对于每个Graph的实例它都会有一个Self.
还是不明白,你在一个实例内部使用自己为什不直接调用Self,而非要通过指向它自身的指针来调用
(请记住,Self本自就是一个指针,它指向对地址在同一个实例中是不会改变的,
但它的存放地址是可能改变的,这个变量是由编译器来维护的).

 
你可以告诉我在什么地方非要用到Self指针,而不能直接通过Self引用吗?
 
呵呵
问题已经搞定了
能多讨论一下更好
我在想如果Self是一个指向TGraph类型的指针
那么为什么这句赋值会出错
// GraphNode[ FGraphNodeNum - 1].Parent is TPGraph;
GraphNodes[ FGraphNodeNum - 1 ].Parent := self ;
// 编译器提示出错
[Error] GraphUnit.pas(1130): Incompatible types: 'TGraph' and 'TPGraph'
本来我还真的没有加那个@ 符号的, 因为这个原因我才使用了@Self
至于为什么要用这么复杂的数据结构,呵呵,我也不想这样。
TGraph里面有若干个TGraphNode,用的是动态数组实现 Array of TGraphNode
每一个TGraphNode有的时候要访问其他TGraphNode
为了这个目的,我就把TGraph的指针给了TGraph所拥有的TGraphNode.Parent 保存
这样可以访问到其他的TGraphNode
兄弟们看看,有什么更好的方法

 
我还是不明白,当然出错啦,一个是TPGraph,一个是TGraph,
问题是为什么一定要定义一个TPGraph类,你把TGraph的Parent属性定义成和它自身一样的TGraph类不就行了吗?
我前面的代码已经说明了.
Type
class GraphNode
public
Parent : TGraph;
//////////////////////////////////////////////////////////////////////////
//这里的Parent是TGraph类而不是TPGraph类,压根就不需要定义一个TPGraph类.
//////////////////////////////////////////////////////////////////////////
end;

class Graph
// .....
GraphNodes: Array of GraphNode;
end;

//.....
//.....
procedure TGraph.AddGraphNode(var Source: TGraphNode);
begin
// ...
GraphNodes[ FGraphNodeNum - 1 ].Parent := self ;

// 还会出错吗,不会了,因为Parent是TGraph类,Self也是TGraph类,
//而且这个TGraph的每个一个GraphNode的父都是这个类的实例.
//...
end;
 
后退
顶部