Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Object Pascal中的父对象和子对象_Object_Freepascal_Delphi - Fatal编程技术网

Object Pascal中的父对象和子对象

Object Pascal中的父对象和子对象,object,freepascal,delphi,Object,Freepascal,Delphi,我有父对象 type PNode=^Node; Node=Object Left,Right:PNode; Balance:integer; Function Is_Greater(Node1:PNode); end; 和对象节点的子对象 Type ChildNode=object(Node); X:integer; end; 我有两个指针p,Q:PNode和use命令 P^:=Q^; 但它

我有父对象

type PNode=^Node;
     Node=Object
        Left,Right:PNode;
        Balance:integer;
        Function Is_Greater(Node1:PNode);
      end;
和对象节点的子对象

Type ChildNode=object(Node);
        X:integer;
       end;
我有两个指针p,Q:PNode和use命令

P^:=Q^;
但它不会改变节点p的X值。
有没有一种方法可以做到这一点,而不使用指向子对象的指针

使用在子对象中重写的虚拟方法

 type 
   PNode = ^TNode;
   TNode = object
               Constructor Init;
               procedure assign(t:pNode); virtual;
              end;

    PChildNode=^TChildNode;
    TChildNode = Object(TNode)
               x:integer;
               procedure assign(t:pNode); virtual;
               end;


 Constructor TNode.Init;
 begin
 end;
 procedure TNode.Assign(t:pNode); 
 begin
 // assign the tnode fields in t to the fields of self
 end;

 procedure TChildNode.Assign(t:pNode); 
 begin
   inherited Assign(t); // parent's fields first
   // we don't have Delphi's "IS" here, so can't test if t really is a pchildnode.
   x:=pchildnode(t)^.x;
 end;

function CreateChildNode(x:integer):PNode;
var chld : pChildNode;
begin
 chld:=new(PChildNode,Init); chld^.x:=x;
 createchildnode:=chld;
end;

// below this no knowledge of TChildnode except for printing.
var p1,p2 : PNode;

begin
 p1:=createchildnode(10);
 p2:=createchildnode(5);
 // p2^ must be equal to P1^ or derive from it. 
 // See comment in TChildNode.assign
 p1^.assign(p2); 
 writeln(pchildnode(p1)^.x);
end.
注意,在您应该使用的等效Delphi方言(类)代码中,您可以使用is操作符测试assign的传入元素是否真的是tchildnode


查看FPC的软件包/tv和对象单元源是学习旧TP方言的一个很好的资源。

由于
PNode
(和
TNode
)没有
X
字段,因此
X
字段没有更改。下面是一些解释和用例的工作代码:

program Project1;

type

    { TNode }

    PNode = ^TNode;
    TNode = object
        a: Integer;
        procedure assign(t:TNode);
    end;

    { TChildNode }

    PChildNode = ^TChildNode;
    TChildNode = object(TNode)
        x: Integer;
        // Overload parent method for the new type
        // Parent method still available via inherited (see below)
        procedure assign(t:TChildNode); overload;
    end;

{ TNode }

procedure TNode.assign(t: TNode);
begin
    a := t.a;
end;

{ TChildNode }

procedure TChildNode.assign(t: TChildNode);
begin
    inherited assign(t); // Call parent method to assign inherited fields values
    x := t.x;
end;

var
    n: TNode;
    cn1, cn2: TChildNode;

    pn, pcn2: PNode;
    pcn1: PChildNode;

begin
    n.a := 10;

    cn1.a := 11;
    cn1.x := 12;

    cn2.a := 21;
    cn2.x := 22;

    Writeln(cn1.a: 10, cn1.x: 10);

    cn1.assign(n);
    //cn1 := n; // Error here, type incompatibility
    Writeln(cn1.a: 10, cn1.x: 10);

    cn1.assign(cn2);
    Writeln(cn1.a: 10, cn1.x: 10);

    cn2.x := 44;
    // Actually this code works like previous
    cn1 := cn2;
    cn2.a := 55;
    Writeln(cn1.a: 10, cn1.x: 10);

    Readln;

    pn := New(PNode);
    pcn1 := New(PChildNode);
    pcn2 := New(PChildNode); // Here we assign PChildNode object to the variable with type PNode

    pn^.a := 10;

    pcn1^.a := 11;
    pcn1^.x := 12;

    pcn2^.a := 21;
    PChildNode(pcn2)^.x := 22; // This explicit conversion is necessary because PNode type of the pcn2 variable

    Writeln(pcn1^.a: 10, pcn1^.x: 10);

    //pcn1^.assign(pn^);
    //pcn1^ := pn^; // Error here, type incompatibility
    PNode(pcn1)^ := pn^;
    Writeln(pcn1^.a: 10, pcn1^.x: 10);

    // Here is X value does not changed because it is absent in the pcn2^ have TNode type
    // and assign method of the TNode will be called
    pcn1^.assign(pcn2^); 
    Writeln(pcn1^.a: 10, pcn1^.x: 10);

    // This code works well
    pcn1^ := PChildNode(pcn2)^;
    pcn2^.a := 55;
    Writeln(pcn1^.a: 10, pcn1^.x: 10);

    Readln;
end.

您可以使用此代码了解有关对象行为的更多信息。

可能我弄错了,但您的代码仍然包含错误:
TChildNode.Assign(t:TNode)
x:=t.x其中
t
没有
x
字段,因为它有
TNode
type.Correct。它只是示意图,我用一个工作程序更新了它。pcn1^。assign仍然在业务代码中添加pcn1是p/tchildnode的信息。虚拟方法stuff修复了这一点,但是忽略了IS运算符以确保安全。@MarcovandeVoort缺少检查参数实际类型的能力是使用重载方法而不是虚拟方法的主要原因。然而,asker似乎对他的问题失去了兴趣。顺便说一句,有一些方法可以绕过它,使用VMT技巧,但这将是特定于编译器的。请参阅tobject.is_对象的源代码。在TP时代,它只是在没有saveguard的情况下使用,但在那里它并没有像Delphi那样作为自动持久化的一部分使用,这使得它更受程序员的控制。也许我们需要一个简单的inheritsof/from方法来避免依赖于此的新代码。Oto没有多少新的TP目标代码是为了好玩而编写的,在Pascal中OOP的演变: