Delphi 在实例变量上访问冲突

Delphi 在实例变量上访问冲突,delphi,interface,reference,Delphi,Interface,Reference,我有两节课。一个抽象(XmlNodeManager)和您的具体子XmlEnpManager。 抽象类定义为: type TXmlNodeManager = class public constructor Create(aRoot: IXMLNode); virtual; abstract; function Size(): Integer; protected { sgy alias para strategy } sgyIte

我有两节课。一个抽象(XmlNodeManager)和您的具体子XmlEnpManager。 抽象类定义为:

type
  TXmlNodeManager = class
    public
      constructor Create(aRoot: IXMLNode); virtual; abstract;
      function Size(): Integer;
   protected
      { sgy alias para strategy }
      sgyIterator: Integer;
      sgyAttributes: TStringList;
      sgyRoot: IXMLNode;
  end;
以及子类:

type
  TXmlEnpManager = class (TXmlNodeManager)
    public
      constructor Create(aRoot: IXMLNode); override;
  end;
构造函数在子类中实现,并具有下一个代码:

constructor TXmlEnpManager.Create(aRoot: IXMLNode);
begin
  sgyIterator := 0;
  sgyRoot := aRoot;
  Self.GenerateAttribs;
end;
而size()方法是在父对象中实现的:

function TXmlNodeManager.Size(): Integer;
begin
  Size := sgyRoot.ChildNodes.Count;
end;
当我创建XmlEnpManager实例,并将定义的IXMLNode作为param传递,然后发送Size()消息时。程序失败(在执行时),在sgyRoot.ChildNodes.Count上出现访问冲突

我做下一个检查:

function TXmlNodeManager.Size(): Integer;
begin
  if (Assigned(sgyRoot)) then
    ShowMessage('Root assigned.')
  else
    ShowMessage('Root not assigned ???');
end;
显示第二个警报。Im是Delphi中最新的,并且怀疑接口引用是按值进行的,而不像对象。对吗?。 如何解决这个问题?有什么想法吗

编辑:我做向下投射。我有一个XmlNodeManager类型的变量,即使用XmlNodeManager的子类初始化。这是正确的吗?。例如:

// aNode can be a instance of TXmlEnpManager or another subclass of TXmlNodeManager.
procedure TXmlFileManager.SetCurrentNode(aNode: TXmlNodeManager);
    begin
      // xmCurrentNode is of TXmlNodeManager type
      xmCurrentNode := aNode;
    end;

如果我没有弄错,您应该从构造函数调用继承的构造函数:

constructor TXmlEnpManager.Create(aRoot: IXMLNode);
begin
  INHERITED Create;
  sgyIterator := 0;
  sgyRoot := aRoot;
  Self.GenerateAttribs;
end;

我仍然建议您在构造函数中执行相同的检查,
如果已分配(aRoot)
,或者“GenerateAttribs”正在覆盖接口。@SertacAkyuz yes,已分配。对不起,我没有解释GenerateAttribs的作用,这个方法只创建了一个TListString,没有更多。@ramiromd:显示调用
TXmlEnpManager.Create()
的代码。给定您显示的代码,调用方可能会将nil
IXMLNode
传递给
Create()
,您应该在
Size()
中检查该值:
如果已分配(sgyRoot),则结果:=sgyRoot.ChildNodes.Count否则结果:=0跟随数据。确认您调用了您认为正在调用的构造函数。然后确认构造函数收到了您认为它收到的接口。最后,确认您调用的
Size
对象与之前调用构造函数得到的对象相同。调试器可以帮助您完成这些步骤中的每一步。如果您自己无法调试此步骤,并且如果您只是尝试,调试看起来非常简单,那么您将需要提供一个SSCCE。继承的构造函数是抽象的,因此编译器将忽略您添加的代码。编译器将发出与问题中的源代码相同的目标代码。更糟糕的是,如果它将编译,则会导致抽象错误(继承的构造函数签名不同)。您错了。继承的构造函数是抽象的,因此忽略调用它显然不是问题的原因。然而,继承调用的缺乏确实表明了类的糟糕设计。构造器可能没有理由是虚拟的,更不用说抽象的了。类应该始终负责初始化自己的字段,因此基类应该是分配给
sgyRoot
sgyIterator
sgyAttributes
的类。如果有什么东西应该是抽象的,那就是
GenerateAttribs
,它应该填充而不是分配
sgyAttributes
。尽管如此,这并不能回答问题。你确定吗?我知道它不会调用直接父级的构造函数(它没有无参数构造函数),但我希望它调用TObject.Create,从而将对象的所有内存清除为零。TObject.Create不做任何事情。是NewInstance,它将对象初始化为零。既然你知道这个答案是错误的,我不明白你为什么不删除它。留下不准确的答案对社区没有帮助。