看下列代码:
//*************************************************************
constructor TComponent.Create(AOwner: TComponent);
begin
FComponentStyle := [csInheritable];
if AOwner <> nil then AOwner.InsertComponent(Self);
end;
//*************************************************************
procedure TComponent.InsertComponent(AComponent: TComponent);
begin
AComponent.ValidateContainer(Self);
ValidateRename(AComponent, '', AComponent.FName);
Insert(AComponent);
AComponent.SetReference(True);
if csDesigning in ComponentState then
AComponent.SetDesigning(True);
Notification(AComponent, opInsert);
end;
//*************************************************************
procedure TComponent.Insert(AComponent: TComponent);
begin
if FComponents = nil then FComponents := TList.Create;
FComponents.Add(AComponent);
AComponent.FOwner := Self;
end;在“将要创建的对象 ”的构造函数执行时,会向“宿主对象”发消息:AOwner.InsertComponent(Self);
“宿主对象”在接到消息时 会调用 “宿主对象”的一个私有方法
Insert(AComponent);
在 “宿主对象”的方法Insert(AComponent)执行时竞然访问了“将要建的对象”的私有成员AComponent.FOwner := Self;有书上说 当几个类 的声明在同一个单元文件中时 这几个类互为友元。
那么“将要创建的对象”所属的类很能不会与 Tcomponet 同在一个单元。所以我想书上说法不正确,
但是 上述问题应怎样解决?
//*************************************************************
constructor TComponent.Create(AOwner: TComponent);
begin
FComponentStyle := [csInheritable];
if AOwner <> nil then AOwner.InsertComponent(Self);
end;
//*************************************************************
procedure TComponent.InsertComponent(AComponent: TComponent);
begin
AComponent.ValidateContainer(Self);
ValidateRename(AComponent, '', AComponent.FName);
Insert(AComponent);
AComponent.SetReference(True);
if csDesigning in ComponentState then
AComponent.SetDesigning(True);
Notification(AComponent, opInsert);
end;
//*************************************************************
procedure TComponent.Insert(AComponent: TComponent);
begin
if FComponents = nil then FComponents := TList.Create;
FComponents.Add(AComponent);
AComponent.FOwner := Self;
end;在“将要创建的对象 ”的构造函数执行时,会向“宿主对象”发消息:AOwner.InsertComponent(Self);
“宿主对象”在接到消息时 会调用 “宿主对象”的一个私有方法
Insert(AComponent);
在 “宿主对象”的方法Insert(AComponent)执行时竞然访问了“将要建的对象”的私有成员AComponent.FOwner := Self;有书上说 当几个类 的声明在同一个单元文件中时 这几个类互为友元。
那么“将要创建的对象”所属的类很能不会与 Tcomponet 同在一个单元。所以我想书上说法不正确,
但是 上述问题应怎样解决?
解决方案 »
- 接口 delphi
- 关于TQuery的编辑状态的问题。
- 请问,delphi 那个控件象 ie 地址显示图标输入框控件呢?
- 关于fastreport的问题
- 本来不是我该得的分,散了吧!
- 如何控制EXCEL的行高和列宽?
- oracle的表在delphi中打开,提示‘invalid datetime format’。
- 一个SQL的日期查询问题。
- 关于mdi的问题,再加100分,解决问题后一起给分!
- 我用clientdataset,SQL SEVERS做了一个主从表,但发现新增主表记录后再新增从表记录后,调用applyupdates后不能正常更新,也未出现出错
- c++的视频教学,要的快下啊。
- 我是Delphi新手,想请各位推荐几本Delphi好书.
begin
if FComponents = nil then FComponents := TList.Create;
FComponents.Add(AComponent);
AComponent.FOwner := Self;
end;
的确,这个楼主的问题不是友元问题,不过这里虽然是对自己实例的一个引用,但也未必这么简单,如下:其实上面三个方法最重要的三句分别是
1.TComponent构造器中的if AOwner <> nil then AOwner.InsertComponent(Self);
2.TComponent.InsertComponent中的Insert(AComponent);
3.TComponent.Insert中的if FComponents = nil then FComponents := TList.Create;仔细看看,很容易看明白,其实这个三个语句组成一个操作链
1中的Self和2中的AComponent其实是一个对象(对一个连续操作而言),同理2中的Insert(AComponent)前面隐含的Self其实就是3中FComponents前面隐含的Self,所以楼主的最后一个判断----“在 “宿主对象”的方法Insert(AComponent)执行时竞然访问了“将要建的对象”的私有成员AComponent.FOwner := Self;”是不正确的,这里访问的是容器的私有数据成员,而不是楼主所说的“将要建的对象”的私有数据成员!所以,这里楼主理解错误!另外,书上的友元的定义没有错误!呵呵....
begin
...
if AOwner <> nil then AOwner.InsertComponent(Self); <---- self 是自身
end;
procedure TComponent.InsertComponent(AComponent: TComponent); <--- 是上面传进来的那个self
begin
...
Insert(AComponent); <--- 还是那个self
...
end;procedure TComponent.Insert(AComponent: TComponent);
begin
...
AComponent.FOwner := Self; <--- AComponent 就是 self
end;明白了? 不是“待创建的对象”
to: FrameSniper(§绕瀑游龙§)
Insert(AComponent)前面隐含的Self其实就是3中FComponents前面隐含的Self,
这里访问的是容器的私有数据成员,而不是楼主所说的“将要建的对象”的私有数据成员! (问1)"FComponents前面隐含的Self" 这句话如何理解?
(问2)在整个过程中 主要有两个对象在活动 一个是“将要创建的对象”,一个是“宿主对象” 所以应有两个 self 指针。
第三个函数(insert)中 的AComponent 存放的是一个self指针
(是“将要创建的对象”的self指针,不是“宿主对象”的self指针),
而这句话 AComponent.FOwner := Self 怎么成了 访问容器的么有数据?
to truezerg(赵明宇) 我理解你的意思是说: AComponent 不是“待创建的对象”
假如AComponent 是“宿主对象”,那么AComponent.FOwner := Self 有何意义呢?
问题1:if FComponents = nil then FComponents := TList.Create;这个话其实就是
if Self.FComponents = Nil then Self.FComponents := TList.Create;这里省略了Self这个隐含参数!这个参数指定的是当前类方法的当前实例;问题2:你的叙述已经存在问题,我把你写的那三个过程重新给你讲解一边,如下--
我们假设宿主对象为A,将被创建对象为B//*************************************************************
constructor TComponent.Create(AOwner: TComponent); //调用这个过程的情况一般是直接调用B所属类的构造器,如TEdit.Create(Application);
begin
FComponentStyle := [csInheritable]; //指定B可被继承
if AOwner <> nil then AOwner.InsertComponent(Self); //将B(这里是Self)插入到A(这里是AOwner)的组件列表中,然后看下面的方法
end;
//*************************************************************
procedure TComponent.InsertComponent(AComponent: TComponent);
//这里的AComponent为上面的B,InsertComponent为上面A的一个可使用方法
begin
AComponent.ValidateContainer(Self); //检测A(这里是Self)是否是一个有效的容器
ValidateRename(AComponent, '', AComponent.FName); //对B检测重命名
Insert(AComponent); //将B插入到A中,这里其实是省略了隐含参数Self,然后看下面这个方法
AComponent.SetReference(True);
if csDesigning in ComponentState then
AComponent.SetDesigning(True);
Notification(AComponent, opInsert);
end;
//*************************************************************
procedure TComponent.Insert(AComponent: TComponent);
begin
//这里FComponents前面隐含的Self其实就是上面过程中的A,所以,这里不是访问“将创建对象”的FComponents,而是宿主对象的FComponents,明白?
if FComponents = nil then FComponents := TList.Create;
FComponents.Add(AComponent);
AComponent.FOwner := Self;
end;
非类方法中的self引用的是调用它的对象!
请看:
AOwner.InsertComponent(Self);
self引用的“待创建的对象” 。
而
AComponent.FOwner := Self;
中的self是引用的“AOwner对象”,即“宿主对象”!
这个是AComponent类的引用,自己和自己当然是友员了!
至于他的派生类中是不是友员的问题,我想是派生类中包含了TComponent的成分.
而TComponent的成分当然和TComponent是友员关系。在C++中,我们不是可以定义某个数据成员是另外一个类的友员吗?
我明白你的意思了,但你还没理解我的意思。
对于语句“AComponent.FOwner := Self ;”
我的意思是 语句等号左边(AComponent.FOwner)是违反的返问规则。FOwner 是私有的。
insert是在“宿主对象”执行的。
而FOwner是“将创建对象”的私有成员。只能通过“将创建对象”的公共方法访问。
(1)insert 方法是声明在 Classes单元 中的一个类的方法;
(2)insert 方法所问的 私有数据(FOwner)也是在Classes单元定义的。
(3)insert 可以看作 Classes 单元中 所有定义类的一个友元函数。
(4)insert 最后被派生类继承了(的确继承了,但是在派生类中不能访问,因为他是私有的),
(5)insert 是classes中所定义的的类的友元函数 这一点在TComponet的派生类是没有变化的。
(6)Insert 仅能访问classes中所定义的的类的私有数据,不能访问派生类的私有数据。
to majorsoft(major):
我刚在 msdn中 c++ Reference 中查了一下,C++中没有 friend 数据成员这一说法.结贴了。