gpt4 book ai didi

Delphi子类构造函数重写

转载 作者:行者123 更新时间:2023-12-03 15:23:09 27 4
gpt4 key购买 nike

我在单个文件中声明了以下类:

type
TCongruence = class(TObject)
private
a, b, n, numClass: integer;
solutions, vals: TSolutions;
hasSolutions: boolean;
function divides(a, b: integer): boolean;
function modulo(a, b: integer): integer;
public
constructor Create(a, b, n: integer); virtual;
function getSolutions: TSolutions; virtual;
function gcdExtended(p, q: integer): TSolutions;
class function getGCD(u, v: integer): integer;
property valA: integer read a;
property valB: integer read b;
property valN: integer read n;
property getClass: integer read numClass;
property hasSol: boolean read hasSolutions;
end;

type
TConguenceSystem = class(TCongruence)
private
system: array of TCongruence;
public
constructor Create(a: array of TCongruence); override;
function getSolutions: integer; override;
end;

如您所见,第二个是一个子类,因为我需要使用 TCongruence 类中实现的所有函数。我已将构造函数声明为 virtual,以便我可以调用后代的重写。

这是正确的吗?我是否必须删除虚拟/覆盖并简单地使用这样的构造函数? (下)

constructor Create(a: array of TCongruence); 

我想在这种情况下我隐藏了父亲的构造函数。我已经声明了这个构造函数:

constructor TConguenceSystem.Create(a: array of TCongruence);
var i: integer;
begin

SetLength(system, length(a)); // private var system: array of TCongruence
for i := Low(a) to High(a) do
begin
system[i] := a[i];
end;

solutions := false;

end;

最佳答案

当您打算在派生类中重写具有相同签名的方法的行为时,您必须在基类中将其声明为virtual,然后派生类将使用覆盖

但是,如果您希望引入具有不同签名的新方法,那么您必须使用overload指令(如果您在同一个类(class)。这只是允许对具有不同签名的实际上完全不同的方法重复使用相同的方法名称。例如:

 TCongruence = class(TObject)
public
constructor Create(a : integer); overload;
constructor Create(a, b, n: integer); overload;
end;

但是,如果您在后代类中声明具有不同签名的新方法,则不需要这些修饰。

 TCongruence = class(TObject)
public
constructor Create(a, b, n: integer);
end;

TCongruenceSystem = class(TCongruence)
public
constructor Create(a: array of TCongruence);
end;

上面的内容很好 - 您没有覆盖原始构造函数,您只是引入一个具有新签名的新构造函数。由于后者属于具有不同名称的新类,因此不会产生歧义,并且不需要重载。您甚至可以在这里以通常的方式访问祖先方法:

 TCongruence = class(TObject)
private
Fa, Fb, Fn : integer;
public
constructor Create(a, b, n: integer);
end;

TCongruenceSystem = class(TCongruence)
private
FArr : array of TCongruence;
public
constructor Create(a: array of TCongruence);
end;

constructor TCongruence.Create(a, b, n: integer);
begin
inherited Create;
Fa := a;
Fb := b;
Fn := n;
end;

constructor TCongruenceSystem.Create(a: array of TCongruence);
var
c : TCongruence;
i : integer;
begin
inherited Create(a[0].Fa, a[1].Fb, a[2].Fn);
SetLength(FArr, Length(a));
i := 0;
for c in a do begin
FArr[i] := c;
Inc(i);
end;
end;

但是,如果没有 overload 指令,则不允许执行以下操作:

var
cs : TCongruenceSystem;
begin
cs := TCongruenceSystem.Create(1, 2, 3);
end.

因为TCongruenceSystem隐藏了基类Create,它接受三个integer参数。但是,如果您允许重载:

 TCongruence = class(TObject)
private
Fa, Fb, Fn : integer;
public
constructor Create(a, b, n: integer); overload;
end;

TCongruenceSystem = class(TCongruence)
private
FArr : array of TCongruence;
public
constructor Create(a: array of TCongruence); overload;
end;

然后将允许上面的 cs := TCongruenceSystem.Create(1, 2, 3); 调用,并且祖先构造函数将用于构建后代类。

这些方法可以组合起来,例如:

 TCongruence = class(TObject)
public
constructor Create(a : integer); overload; virtual; {overridable}
constructor Create(a, b, n: integer); overload; {only in base}
end;

TCongruenceSystem = class(TCongruence)
public
constructor Create(a:integer); overload; override; {overrides parent}
constructor Create(a: string); overload; {introduce new}
end;

对于构造函数,您将引入一个具有不同参数集的方法,因此这是允许的。然而,在 getSolutions 的情况下,该函数不带参数,仅返回类型不同。然而,重载方法需要具有不同的参数集,因此在后代类中不允许这种类型的突变。如果您希望子孙类中的 getSolutions 也成为具有不同返回类型的无参数函数,则需要使用不同的名称。

关于Delphi子类构造函数重写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43469404/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com