了解构造函数可见性

Ian*_*oyd 6 delphi constructor delphi-5 constructor-chaining

这是两个简单的类,最初都没有关键字(虚拟,重载,覆盖,重新引入):

TComputer = class(TObject)
public
   constructor Create(Teapot: Integer);
end;

TCellPhone = class(TComputer)
public
   constructor Create(Teapot: Integer; Handle: string);
end;
Run Code Online (Sandbox Code Playgroud)

我会将这些以上的定义表示为略短的:

TComputer = class(TObject)
   constructor Create(Teapot: Integer);

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);
Run Code Online (Sandbox Code Playgroud)

构造时TCellPhone只有一个构造函数(int,string) - 因为祖先构造函数已被隐藏.我将指出可见的构造函数TCellPhone:

  • 茶壶:整数; 句柄:字符串

现在对于这个问题,前3个案例是有意义的,第4个案例没有:

1.祖先构造函数由后代隐藏:

TComputer = class(TObject)
   constructor Create(Teapot: Integer);

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);
Run Code Online (Sandbox Code Playgroud)
  • Teapot: Integer; Handle: string

这是有道理的,祖先构造函数是隐藏的,因为我已经声明了一个新的构造函数.

2.祖先虚拟构造函数由后代隐藏:

TComputer = class(TObject)
   constructor Create(Teapot: Integer); virtual;

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);
Run Code Online (Sandbox Code Playgroud)
  • Teapot: Integer; Handle: string

这是有道理的,祖先构造函数是隐藏的,因为我已经声明了一个新的构造函数.

注意:因为祖先是虚拟的:Delphi会警告你,你正在隐藏虚拟祖先(在上一个隐藏静态构造函数的例子中:没人关心,所以没有警告).可以抑制警告(意思是"是的是的,我隐藏了一个虚拟构造函数.我 打算这样做.")通过添加重新引入:

    TComputer = class(TObject)
       constructor Create(Teapot: Integer); virtual;

    TCellPhone = class(TComputer)
       constructor Create(Teapot: Integer; Handle: string); reintroduce;
Run Code Online (Sandbox Code Playgroud)

3.由于超载而未隐藏在后代中的祖先构造函数:

TComputer = class(TObject)
   constructor Create(Teapot: Integer);

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string); overload;
Run Code Online (Sandbox Code Playgroud)
  • Teapot: Integer; Handle: string
  • Teapot: Integer

这是有道理的,因为后代构造函数是祖先的重载,因此允许两者都存在.祖先构造函数未被隐藏.

4.由于重载而未隐藏在后代中的虚拟祖先构造函数 - 但仍会收到警告:

这是没有意义的情况:

TComputer = class(TObject)
   constructor Create(Teapot: Integer); virtual;

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string); overload;
Run Code Online (Sandbox Code Playgroud)
  • Teapot: Integer; Handle: string
  • Teapot: Integer

    方法'Create'隐藏基类型'TComputer'的虚方法

这没什么意义.祖先不仅没有被隐藏,后代也被超载; 它甚至不应该抱怨.

是什么赋予了?

Mar*_*ams 5

德尔福的文档说:

如果重载虚方法,请在后代类中重新引用它时使用reintroduce指令.例如,

type
  T1 = class(TObject)
    procedure Test(I: Integer); overload; virtual;
  end;
  T2 = class(T1)
    procedure Test(S: string); reintroduce; overload;
  end;
Run Code Online (Sandbox Code Playgroud)

如果没有重新引入指令,它仍然有效,正如您所注意到的那样,但您会得到警告.

此外,您实际上隐藏了TObject.Create,但它与警告无关.如果您认为您也可能想要访问TObject.Create,请执行以下操作:

type
  TComputer = class(TObject)
    constructor Create(Teapot: Integer); reintroduce; overload; virtual;
  end;

type
  TCellPhone = class(TComputer)
    constructor Create(Teapot: Integer; Handle: String); reintroduce; overload;
  end;
Run Code Online (Sandbox Code Playgroud)