了解构造函数的可见性

发布于 2024-09-26 20:52:40 字数 2646 浏览 0 评论 0原文

这是两个简单的类,最初都没有关键字(virtual、overload、override、reintroduce):

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

TCellPhone = class(TComputer)
public
   constructor Create(Teapot: Integer; Handle: string);
end;

我将把上面的定义表示为稍短一些:

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);

并且在构造 TCellPhone 时,只有一个构造函数(>int, string) - 因为祖先构造函数已被隐藏。我将把 TCellPhone 的可见构造函数指示为:

  • Teapot: Integer; Handle: string

现在对于问题来说,前 3 种情况有意义,第 4 种则不然:

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

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);
  • Teapot: Integer; Handle: string

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

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

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);
  • Teapot: Integer; Handle: string

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

注意:因为祖先是虚拟的:Delphi 会警告您 你隐藏了虚拟祖先(在 前面隐藏的示例 静态构造函数:没人关心,所以 没有警告)。警告可以是 压抑(意思是“是啊是啊, 我隐藏了一个虚拟构造函数。我 打算这样做。”)通过添加重新引入

<前><代码> TComputer = 类(TObject) 构造函数 Create(茶壶: Integer);虚拟的; TCellPhone = 类(TComputer) 构造函数 Create(Teapot: Integer; Handle: string);重新引入;

3.由于重载,祖先构造函数未隐藏在后代中:

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string); overload;
  • 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;
  • Teapot: Integer: string;
  • 茶壶:整数

    方法“Create”隐藏基类型“TComputer”的虚拟方法

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

什么给?

Here's two simple classes, initially both have no keywords (virtual, overload, override, reintroduce):

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

TCellPhone = class(TComputer)
public
   constructor Create(Teapot: Integer; Handle: string);
end;

i will represent these above defintions as the slightly shorter:

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);

And when constructing TCellPhone there is only one constructor (int, string) - because the ancestor constructor has been hidden. i will indicate the visible constructors of TCellPhone as:

  • Teapot: Integer; Handle: string

Now for the question, the first 3 cases make sense, the 4th does not:

1. Ancestor constructor is hidden by descendant:

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);
  • Teapot: Integer; Handle: string

This makes sense, the ancestor constructor is hidden because i've declared a new constructor.

2. Ancestor virtual constructor is hidden by descendant:

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string);
  • Teapot: Integer; Handle: string

This makes sense, the ancestor constructor is hidden because i've declared a new constructor.

Note: Because the ancestor is virtual: Delphi will warn you that
you're hiding the virtual ancestor (in
the previous example of hiding a
static constructor: nobody cares, so
no warning). The warning can be
suppressed (meaning "Yeah yeah yeah,
i'm hiding a virtual constructor. i
meant to do that.") by adding reintroduce:

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

    TCellPhone = class(TComputer)
       constructor Create(Teapot: Integer; Handle: string); reintroduce;

3. Ancestor constructor not hidden in descendant because of overloading:

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string); overload;
  • Teapot: Integer; Handle: string
  • Teapot: Integer

This makes sense, since the descendant constructor is an overload of the ancestor, so both are allowed to be present. The ancestor constructor is not being hidden.

4. Virtual ancestor constructor not hidden in descendant because overloading - but still get a warning:

This is the case that makes no sense:

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

TCellPhone = class(TComputer)
   constructor Create(Teapot: Integer; Handle: string); overload;
  • Teapot: Integer; Handle: string
  • Teapot: Integer

    Method 'Create' hides virtual method of base type 'TComputer'

This makes little sense. Not only is the ancestor not hidden, the descendant is overloaded; it shouldn't even be complaining.

What gives?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

榆西 2024-10-03 20:52:40

德尔福的文档说:

如果重载虚拟方法,请使用
当您重新引入指令时
在后代类中重新声明它。
例如,

<前><代码>类型
T1 = 类(TObject)
程序测试(I:整数);超载;虚拟的;
结尾;
T2 = 类别(T1)
过程测试(S:字符串);重新引入;超载;
结尾;

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

另外,您实际上隐藏了 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;

Delphi's documentation says:

If you overload a virtual method, use
the reintroduce directive when you
redeclare it in descendant classes.
For example,

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

Without the reintroduce directive, it still works, as you've noticed, but you'll get the warning.

Also, you are actually hiding TObject.Create, but it has nothing to do with the warning. If you think you might want access to TObject.Create also, do this:

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;
南薇 2024-10-03 20:52:40

我同意特立尼达的观点。警告背后的逻辑可能只查看祖先方法是否是虚拟/动态以及后代方法是否被标记为覆盖或重新引入。

这也适用于“正常”方法。

可以通过将 reintroduce 放在 overload 修饰符之前或通过将重写的构造函数添加到仅委托给祖先构造函数的后代类来抑制它。

I would agree with Trinidad. The logic behind the warning probably only looks at whether the ancestor method is virtual/dynamic and whether a descendant method is marked as override or reintroduce.

This also applies to "normal" methods as well.

It can be suppressed by putting reintroduce before the overload modifier or by adding an overridden constructor to the descendant class that simply delegates to the ancestor constructor.

£噩梦荏苒 2024-10-03 20:52:40

我已经注意到了这一点。据我所知,该警告是一个错误,因为继承的方法没有隐藏。
如果尚未报告,则应在 qc.embarcadero.com 上报告。

I've already noticed that. The warning is a bug, as far as I can tell, because the inherited method is not hidden.
Should be reported at qc.embarcadero.com, if it isn't already.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文