我有一个类层次结构,这个:
type
TMatrix = class
protected
//...
public
constructor Create(Rows, Cols: Byte);
//...
type
TMinMatrix = class(TMatrix)
private
procedure Allocate;
procedure DeAllocate;
public
constructor Create(Rows, Cols: Byte);
constructor CreateCopy(var that: TMinMatrix);
destructor Destroy;
end;
如您所见,派生类和基类构造函数都具有相同的参数列表。 我从派生的一个显式调用基类构造函数:
constructor TMinMatrix.Create(Rows, Cols: Byte);
begin
inherited;
//...
end;
是否有必要在Delphi中显式调用基类构造函数?可能是我需要放置重载或覆盖以清除我打算做什么?我知道如何在C ++中实现它 - 只有当你想要传递一些参数时才需要显式调用基类构造函数 - 但我在Delphi编程方面没有多少经验。
答案 0 :(得分:14)
据我所知,这里有两个不同的问题:
您必须显式调用基类的构造函数:
constructor TMinMatrix.Create(Rows, Cols: Byte);
begin
inherited;
//...
end;
你还必须使子类'构造函数override
和基类'构造函数virtual
,以确保编译器看到之间的关系二。如果你不这样做,编译器可能会警告你TMinMatrix的构造函数“隐藏”了TMatrix的构造函数。所以,正确的代码是:
type
TMatrix = class
protected
//...
public
constructor Create(Rows, Cols: Byte); virtual; // <-- Added "virtual" here
//...
type
TMinMatrix = class(TMatrix)
private
//...
public
constructor Create(Rows, Cols: Byte); override; // <-- Added "override" here
constructor CreateCopy(var that: TMinMatrix);
destructor Destroy; override; // <-- Also make the destructor "override"!
end;
请注意,您还应该使用析构函数override
。
请注意,您只能使用相同的参数列表覆盖构造函数。如果子类需要具有不同参数的构造函数,并且您希望阻止直接调用基类的构造函数,则应编写:
type
TMyMatrix = class(TMatrix)
//...
public
constructor Create(Rows, Cols, InitialValue: Byte); reintroduce; virtual;
//...
end
implementation
constructor TMyMatrix.Create(Rows, Cols, InitialValue: Byte);
begin
inherited Create(Rows, Cols); // <-- Explicitly give parameters here
//...
end;
我希望这会让事情更清楚......祝你好运!
答案 1 :(得分:3)
重载,告诉编译器一个方法具有不同参数的相同名称。
覆盖,告诉编译器一个方法覆盖它在基类中声明的虚拟或动态。
重新引入,将隐藏在基类中声明的虚拟或动态方法。
这些定义来自Ray Lischner的书籍{简称Delphi}
type
TFirst = class
private
FValue: string;
FNumber: Integer;
public
constructor Create(AValue: string; ANumber: integer);
property MyValue: string read FValue write FValue;
property MyNumber: Integer read Fnumber write FNumber;
end;
TSecond = class(TFirst)
public
constructor Create(AValue: string; ANumber: Integer);
end;
constructor TFirst.Create(AValue: string; ANumber: integer);
begin
MyValue := AValue;
MyNumber := ANumber;
end;
{ TSecond }
constructor TSecond.Create(AValue: string; ANumber: Integer);
begin
inherited;
end;
声明的TSecond将调用TFirst的创建,没有继承,TSecond成员保持为空。
答案 2 :(得分:3)
您需要显式调用继承的方法;德尔福不会为你做这件事。这是设计使然,因为在某些情况下您正在使用虚拟方法,例如,当您不想调用继承的行为时。
另外,作为个人喜好,我喜欢完全写出继承的电话。 (继承创建(行,列);而不仅仅是继承; ,原因很简单:它使遍历代码变得更容易。如果你有写出一个方法调用,你可以控制点击它并进入祖先方法。
答案 3 :(得分:2)
如果两个构造函数具有相同的名称,则需要重载。
type
TMatrix = class
protected
//...
public
constructor Create(Rows, Cols: Byte);
//...
type
TMinMatrix = class(TMatrix)
public
constructor Create(Rows, Cols: Byte); overload;
constructor Create(var that: TMinMatrix); overload;
end;
最好调用继承的构造函数。
constructor TMinMatrix.Create(Rows, Cols: Byte);
begin
inherited Create(Rows, Cols); // Need to call the full name if the parameters are changed.
//...
end;