了解构造函数的可见性
这是两个简单的类,最初都没有关键字(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
德尔福的文档说:
如果没有重新引入指令,它仍然有效,正如您所注意到的,但您会收到警告。
另外,您实际上隐藏了 TObject.Create,但它与警告无关。如果您认为您可能还想访问 TObject.Create,请执行以下操作:
Delphi's documentation says:
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:
我同意特立尼达的观点。警告背后的逻辑可能只查看祖先方法是否是虚拟/动态以及后代方法是否被标记为覆盖或重新引入。
这也适用于“正常”方法。
可以通过将
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 theoverload
modifier or by adding an overridden constructor to the descendant class that simply delegates to the ancestor constructor.我已经注意到了这一点。据我所知,该警告是一个错误,因为继承的方法没有隐藏。
如果尚未报告,则应在 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.