Delphi:了解构造函数

发布于 2024-09-27 01:07:16 字数 4749 浏览 9 评论 0原文

我希望理解

  • 虚拟
  • 重写
  • 重载
  • 重新引入

在应用于对象构造函数时 。每次我随机添加关键字,直到编译器关闭 - 并且(在使用 Delphi 开发 12 年之后)我宁愿知道我在做什么,而不是随机尝试。

给定一组假设的对象:

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

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

TiPhone = class(TCellPhone)
public
    constructor Create(Cup: Integer); override;
    constructor Create(Cup: Integer; Teapot: string); override;
end;

我希望它们的行为方式可能从声明中显而易见,但是:

  • TComputer具有简单的构造函数,并且后代可以覆盖它
  • TCellPhone具有一个备用构造函数,后代可以重写它
  • TiPhone 重写两个构造函数,调用每个构造函数的继承版本

。现在代码无法编译。我想了解为什么它不起作用。我还想了解重写构造函数的正确方法。或者也许你永远无法覆盖构造函数?或者也许重写构造函数是完全可以接受的?也许您永远不应该拥有多个构造函数,也许拥有多个构造函数是完全可以接受的。

我想了解原因。那么修复它就很明显了。

另请参阅

编辑: 我也想得到一些推理按照虚拟覆盖重载重新引入的顺序。因为当尝试所有关键字组合时,组合数量会爆炸:

  • virtual;超载;
  • 虚拟的;覆盖;
  • 覆盖;超载;
  • 覆盖;虚拟的;
  • 虚拟的;覆盖;超载;
  • 虚拟的;超载;覆盖;
  • 超载;虚拟的;覆盖;
  • 覆盖;虚拟的;超载;
  • 覆盖;超载;虚拟的;
  • 超载;覆盖;虚拟的;
  • 等等

编辑2:我想我们应该从“给定的对象层次结构是否可能?”开始,如果不可能,为什么不呢?例如,拥有来自祖先的构造函数从根本上来说是错误的吗?

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

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

我希望 TCellPhone 现在有两个构造函数。但我在 Delphi 中找不到关键字组合,使其认为这是有效的做法。我认为我可以在 TCellPhone 中拥有两个构造函数,这从根本上是错误的吗?


注意:此行下方的所有内容都不是回答问题所必需的 问题 - 但这确实有助于解释 我的想法。或许你可以看到, 根据我的思维过程,什么 我缺少的基本部分 让一切变得清晰起来。

现在这些声明无法编译:

//Method Create hides virtual method of base type TComputer:
TCellPhone = class(TComputer)
   constructor Create(Cup: Integer; Teapot: string);  virtual;

//Method Create hides virtual method of base type TCellPhone:
TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer); override;
   constructor Create(Cup: Integer; Teapot: string); overload;  <--------
end;

所以首先我将尝试修复TCellPhone。我将首先随机添加 overload 关键字(我知道我不想要 reintroduce 因为这会隐藏其他构造函数,这是我不想要的):

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer; Teapot: string); virtual; overload;
end;

但是失败:在方法或属性之后不允许进行字段定义

我从经验中知道,即使我在方法或属性后面没有字段,如果我颠倒 virtualoverload 关键字的顺序:Delphi 将关闭上:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer; Teapot: string); overload; virtual; 
end;

但我仍然收到错误:

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

所以我尝试删除这两个关键字:

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

但我仍然收到错误:

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

所以我现在放弃自己尝试重新引入

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

现在TCellPhone可以编译,但它使TiPhone的情况变得更糟:

TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer); override; <-----cannot override a static method
   constructor Create(Cup: Integer; Teapot: string); override; <-----cannot override a static method
end;

两者都抱怨我不能覆盖它们,所以我删除了 override 关键字:

TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer);
   constructor Create(Cup: Integer; Teapot: string);
end;

但是现在第二个创建说它必须标记为重载,我这样做了(事实上,我将两者都标记为重载,因为我知道会发生什么如果我不这样做):

TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer); overload;
   constructor Create(Cup: Integer; Teapot: string); overload;
end;

interface 部分一切都很好。不幸的是我的实现不起作用。我的TiPhone的单参数构造函数无法调用继承的构造函数:

constructor TiPhone.Create(Cup: Integer);
begin
    inherited Create(Cup); <---- Not enough actual parameters
end;

i'm looking to understand

  • virtual
  • override
  • overload
  • reintroduce

when applied to object constructors. Every time i randomly add keywords until the compiler shuts up - and (after 12 years of developing with Delphi) i'd rather know what i'm doing, rather than trying things randomly.

Given a hypothetical set of objects:

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

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

TiPhone = class(TCellPhone)
public
    constructor Create(Cup: Integer); override;
    constructor Create(Cup: Integer; Teapot: string); override;
end;

The way i want them to behave is probably obvious from the declarations, but:

  • TComputer has the simple constructor, and descendants can override it
  • TCellPhone has an alternate constructor, and descendants can override it
  • TiPhone overrides both constructors, calling the inherited version of each

Now that code doesn't compile. i want to understand why it doesn't work. i also want to understand the proper way to override constructors. Or perhaps you could never override constructors? Or perhaps it is perfectly acceptable to override constructors? Perhaps you should never have multiple constructors, perhaps it is perfectly acceptable to have multiple constructors.

i want to understand the why. Fixing it would then be obvious.

See also

Edit: i'm also looking to get some reasoning on the order of virtual, override, overload, reintroduce. Because when trying all combinations of keywords, the number of combinations explodes:

  • virtual; overload;
  • virtual; override;
  • override; overload;
  • override; virtual;
  • virtual; override; overload;
  • virtual; overload; override;
  • overload; virtual; override;
  • override; virtual; overload;
  • override; overload; virtual;
  • overload; override; virtual;
  • etc

Edit 2: i guess we should begin with "is the object hierarchy given even possible?" If not, why not? For example, is it fundamentally incorrect to have a constructor from an ancestor?

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

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

i would expect that TCellPhone now has two constructors. But i can't find the combination of keywords in Delphi to make it think that's a valid thing to do. Am i fundamentally wrong in thinking i can have two constructors here in TCellPhone?


Note: Everything below this line is not strictly needed to answer the
question - but it does help to explain
my thinking. Perhaps you can see,
based on my thought processes, what
fundamental piece i'm missing that
makes everything clear.

Now these declarations don't compile:

//Method Create hides virtual method of base type TComputer:
TCellPhone = class(TComputer)
   constructor Create(Cup: Integer; Teapot: string);  virtual;

//Method Create hides virtual method of base type TCellPhone:
TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer); override;
   constructor Create(Cup: Integer; Teapot: string); overload;  <--------
end;

So first i'll trying fixing TCellPhone. i'll start by randomly adding the overload keyword (i know i don't want reintroduce because that would hide the other constructor, which i don't want):

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer; Teapot: string); virtual; overload;
end;

But that fails: Field definition not allowed after methods or properties.

i know from experience that, even though i don't have a field after a method or property, if i reverse the order of the virtual and overload keywords: Delphi will shut up:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer; Teapot: string); overload; virtual; 
end;

But i still get the error:

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

So i try removing both keywords:

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

But i still get the error:

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

So i resign myself to now trying reintroduce:

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

And now TCellPhone compiles, but it has made things much worse for TiPhone:

TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer); override; <-----cannot override a static method
   constructor Create(Cup: Integer; Teapot: string); override; <-----cannot override a static method
end;

Both are complaining that i cannot override them, so i remove the override keyword:

TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer);
   constructor Create(Cup: Integer; Teapot: string);
end;

But now the 2nd create says it must be marked with overload, which i do (in fact i'll mark both as overload, since i know what will happen if i don't):

TiPhone = class(TCellPhone)
public
   constructor Create(Cup: Integer); overload;
   constructor Create(Cup: Integer; Teapot: string); overload;
end;

All all is good in the interface section. Unfortunately my implementations won't work. My single parameter constructor of TiPhone cannot call the inherited constructor:

constructor TiPhone.Create(Cup: Integer);
begin
    inherited Create(Cup); <---- Not enough actual parameters
end;

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

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

发布评论

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

评论(4

终陌 2024-10-04 01:07:16

我发现您的原始声明集不能干净地编译有两个原因:

  1. TCellPhone 中应该有一个警告,其构造函数隐藏基类的方法。这是因为基类方法是虚拟的,并且编译器担心您引入了同名的新方法而不覆盖基类方法。签名不同并不重要。如果您的意图确实是隐藏基类的方法,那么您需要在后代声明上使用reintroduce,正如您的盲目猜测之一所示。该指令的唯一目的是消除警告;它对运行时行为没有影响。

    忽略稍后 TIPhone 将会发生的情况,以下 TCellPhone 声明就是您想要的。它隐藏了祖先方法,但您也希望它是虚拟的。它不会继承祖先方法的虚拟性,因为它们是两个完全独立的方法,只是碰巧具有相同的名称。因此,您还需要在新声明上使用virtual

    TCellPhone = 类(TComputer)
    民众
      构造函数 Create(杯子: 整数; 茶壶: 字符串);重新引入;虚拟的;
    结尾;
    

    基类构造函数 TComputer.Create 也隐藏了其祖先 TObject.Create 的方法,但由于TObject 中的方法不是虚拟的,编译器不会对此发出警告。隐藏非虚拟方法时常发生,并且通常不引人注目。

  2. 您应该在 TIPhone 中收到错误,因为不再有任何需要重写的单参数构造函数。您将其隐藏在 TCellPhone 中。由于您想要有两个构造函数,因此 reintroduce 显然不是之前使用的正确选择。您不想隐藏基类构造函数;你想用另一个构造函数来增强它。

    由于您希望两个构造函数具有相同的名称,因此需要使用 overload 指令。该指令需要在所有原始声明中使用 - 第一次引入每个不同的签名后代中的后续声明。我认为所有声明(甚至是基类)都需要它,这样做并没有什么坏处,但我想这不是必需的。因此,您的声明应如下所示:

    TComputer = 类(TObject)
    民众
      构造函数 Create(Cup: Integer);
        超载; // 允许后代添加更多名为 Create 的构造函数。
        虚拟的; // 允许后代重新实现此构造函数。
    结尾;
    
    TCellPhone = 类(TComputer)
    民众
      构造函数 Create(杯子: 整数; 茶壶: 字符串);
        超载; // 添加另一个名为 Create 的方法。
        虚拟的; // 允许后代重新实现此构造函数。
    结尾;
    
    TiPhone = 类(TCellPhone)
    民众
      构造函数 Create(Cup: Integer);
        覆盖; // 重新实现祖先的 Create(Integer)。
      构造函数 Create(杯子: 整数; 茶壶: 字符串);
        覆盖; // 重新实现祖先的 Create(Integer, string)。
    结尾;
    

现代文档 告诉一切内容应按什么顺序进行:

重新引入超载绑定调用约定摘要警告

其中绑定虚拟动态覆盖调用约定registerpascalcdeclstdcall安全调用; 警告平台已弃用


这是六个不同的类别,但根据我的经验,任何声明中很少有超过三个的类别。 (例如,需要指定调用约定的函数可能不是方法,因此它们不能是虚拟的。)我从来不记得顺序;直到今天我才看到它的记录。相反,我认为记住每个指令的目的更有帮助。当您记住不同任务需要哪些指令时,您最终只会得到两到三个指令,然后就可以非常简单地进行试验以获得有效的指令。编译器可能接受多个顺序,但不用担心 - 顺序对于确定含义并不重要。编译器接受的任何顺序都将具有与其他任何顺序相同的含义(调用约定除外;如果您提到其中多个顺序,则只有最后一个有效,所以不要这样做)。

因此,您只需记住每个指令的目的,并考虑哪些指令放在一起没有任何意义。例如,您不能同时使用reintroduceoverride,因为它们具有相反的含义。而且您不能同时使用virtualoverride,因为其中一个暗示着另一个。

如果您堆积了很多指令,那么您始终可以在计算出所需的其余指令时将overload从图片中剔除。为您的方法指定不同的名称,找出它们自己需要哪些其他指令,然后在再次为它们提供相同的名称时添加overload

I see two reasons your original set of declarations shouldn't compile cleanly:

  1. There should be a warning in TCellPhone that its constructor hides the method of the base class. This is because the base-class method is virtual, and the compiler worries that you're introducing a new method with the same name without overriding the base-class method. It doesn't matter that the signatures differ. If your intention is indeed to hide the method of the base class, then you need to use reintroduce on the descendant declaration, as one of your blind guesses showed. The sole purpose of that directive is to quell the warning; it has no effect on run-time behavior.

    Ignoring what's going to happen with TIPhone later on, the following TCellPhone declaration is what you'd want. It hides the ancestor method, but you want it to be virtual as well. It won't inherit the virtualness of the ancestor method because they're two completely separate methods that just happen to have the same name. Therefore, you need to use virtual on the new declaration as well.

    TCellPhone = class(TComputer)
    public
      constructor Create(Cup: Integer; Teapot: string); reintroduce; virtual;
    end;
    

    The base-class constructor, TComputer.Create, is also hiding a method of its ancestor, TObject.Create, but since the method in TObject is not virtual, the compiler doesn't warn about it. Hiding non-virtual methods happens all the time and is generally unremarkable.

  2. You should get an error in TIPhone because there is no longer any one-argument constructor to override. You hid it in TCellPhone. Since you want to have two constructors, reintroduce clearly wasn't the right choice to use earlier. You don't want to hide the base-class constructor; you want to augment it with another constructor.

    Since you want both constructors to have the same name, you need to use the overload directive. That directive needs to be used on all the original declarations — the first time each distinct signature is introduced subsequent declarations in descendants. I thought it was required on all declarations (even the base class), and it doesn't hurt to do that, but I guess it's not required. So, your declarations should look like this:

    TComputer = class(TObject)
    public
      constructor Create(Cup: Integer);
        overload; // Allow descendants to add more constructors named Create.
        virtual;  // Allow descendants to re-implement this constructor.
    end;
    
    TCellPhone = class(TComputer)
    public
      constructor Create(Cup: Integer; Teapot: string);
        overload; // Add another method named Create.
        virtual;  // Allow descendants to re-implement this constructor.
    end;
    
    TiPhone = class(TCellPhone)
    public
      constructor Create(Cup: Integer);
        override; // Re-implement the ancestor's Create(Integer).
      constructor Create(Cup: Integer; Teapot: string);
        override; // Re-implement the ancestor's Create(Integer, string).
    end;
    

Modern documentation tells what order everything should go in:

reintroduce; overload; binding; calling convention; abstract; warning

where binding is virtual, dynamic, or override; calling convention is register, pascal, cdecl, stdcall, or safecall; and warning is platform, deprecated, or library.

Those are six different categories, but in my experience, it's rare to have more than three on any declaration. (For example, functions that need calling conventions specified probably aren't methods, so they can't be virtual.) I never remember the order; I've never seen it documented till today. Instead, I think it's more helpful to remember each directive's purpose. When you remember which directives you need for different tasks, you'll end up with just two or three, and then it's pretty simple to experiment to get a valid order. The compiler might accept multiple orders, but don't worry — order isn't important in determining meaning. Any ordering the compiler accepts will have the same meaning as any other (except for calling conventions; if you mention more than one of those, only the last one counts, so don't do that).

So, then you just have to remember the purpose of each directive, and think about which ones don't make any sense together. For example, you cannot use reintroduce and override at the same time because they have opposite meanings. And you can't use virtual and override together because one implies the other.

If you have lots of directives piling up, you can always cut overload out of the picture while you work out the rest of the directives you need. Give your methods different names, figure out which of the other directives they need by themselves, and then add overload back while you give them all the same names again.

霊感 2024-10-04 01:07:16

请注意,我没有 Delphi 5,因此我的答案基于最新版本 Delphi XE。我认为这不会真正产生任何影响,但如果确实如此,我们已经警告过您。 :)

这主要基于 http://docwiki.embarcadero.com/RADStudio/en/Methods< /a>,这是方法如何工作的当前文档。您的 Delphi 5 帮助文件可能也有与此类似的内容。

首先,虚拟构造函数在这里可能没有多大意义。在某些情况下您确实需要这样做,但这可能不是一种。看看http://docwiki.embarcadero.com/RADStudio/en/Class_References对于确实需要虚拟构造函数的情况 - 如果您在编码时始终知道对象的类型,但是,您并不知道。

然后,您在 1 参数构造函数中遇到的问题是您的父类本身没有 1 参数构造函数 - 继承的构造函数不会公开。您不能使用inherited在层次结构中向上移动多个级别,您只能调用您的直接父级。您将需要使用一些默认值调用 2 参数构造函数,或者也向 TCellPhone 添加 1 参数构造函数。

一般来说,这四个关键字具有以下含义:

  • virtual - 将其标记为您需要运行时调度的函数(允许多态行为)。这仅适用于初始定义,不适用于子类中的重写。
  • override - 为虚拟方法提供新的实现。
  • overload - 将一个函数标记为与另一个函数同名,但参数列表不同。
  • reintroduce - 告诉编译器您实际上打算隐藏虚拟方法,而不是仅仅忘记提供覆盖

文档中详细说明了所需的订购:

方法声明可以包括
未使用的特殊指令
与其他函数或过程。
指令应该出现在类中
仅声明,不在定义中
声明,并且应该始终是
按以下顺序列出:

重新引入;超载;绑定;
调用约定;抽象的;警告

其中绑定是虚拟的、动态的或
覆盖;调用约定是
寄存器、pascal、cdecl、stdcall 或
安全呼叫;警告是平台,
已弃用,或库。

Note that I don't have Delphi 5, so I'm basing my answers off the newest version, Delphi XE. I don't think that will really make any difference here, but if it does, you've been warned. :)

This is mostly based on http://docwiki.embarcadero.com/RADStudio/en/Methods, which is the current documentation of how methods work. Your Delphi 5 help file probably has something similar to this as well.

First off, a virtual constructor may not make much sense here. There are a few cases where you do want this, but this probably isn't one. Take a look at http://docwiki.embarcadero.com/RADStudio/en/Class_References for a situtation where you do need a virtual constructor - if you always know the type of your objects when coding, however, you don't.

The problem you then get in your 1-parameter constructor is that your parent class doesn't have a 1-parameter constructor itself - inherited constructors are not exposed. You can't use inherited to go up multiple levels in the hierarchy, you can only call your immediate parent. You will need to call the 2-parameter constructor with some default value, or add a 1-parameter constructor to TCellPhone as well.

In general, the four keywords have the following meanings:

  • virtual - Mark this as a function where you will want run-time dispatching (allows polymorphic behavior). This is only for the initial definition, not when overriding in subclasses.
  • override - Provide a new implementation for a virtual method.
  • overload - Mark a function with the same name as another function, but a different parameter list.
  • reintroduce - Tell the compiler you actually intended to hide a virtual method, instead of merely forgetting to supply override.

The ordering required is detailed in the documentation:

Method declarations can include
special directives that are not used
with other functions or procedures.
Directives should appear in the class
declaration only, not in the defining
declaration, and should always be
listed in the following order:

reintroduce; overload; binding;
calling convention; abstract; warning

where binding is virtual, dynamic, or
override; calling convention is
register, pascal, cdecl, stdcall, or
safecall; and warning is platform,
deprecated, or library.

风吹雨成花 2024-10-04 01:07:16

这是所需定义的有效实现:

program OnConstructors;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type

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

TCellPhone = class(TComputer)
public
    constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;

TiPhone = class(TCellPhone)
public
    constructor Create(Cup: Integer); overload; override;
    constructor Create(Cup: Integer; Teapot: string); override;
end;

{ TComputer }

constructor TComputer.Create(Cup: Integer);
begin
  Writeln('Computer: cup = ', Cup);
end;

{ TCellPhone }

constructor TCellPhone.Create(Cup: Integer; Teapot: string);
begin
  inherited Create(Cup);
  Writeln('Cellphone: teapot = ', Teapot);
end;

{ TiPhone }

constructor TiPhone.Create(Cup: Integer);
begin
  inherited Create(Cup);
  Writeln('iPhone: cup = ', Cup);
end;

constructor TiPhone.Create(Cup: Integer; Teapot: string);
begin
  inherited;
  Writeln('iPhone: teapot = ', Teapot);
end;

var
  C: TComputer;

begin

  C := TComputer.Create(1);
  Writeln; FreeAndNil(C);

  C := TCellPhone.Create(2);
  Writeln; FreeAndNil(C);
  C := TCellPhone.Create(3, 'kettle');
  Writeln; FreeAndNil(C);

  C := TiPhone.Create(4);
  Writeln; FreeAndNil(C);
  C := TiPhone.Create(5, 'iPot');

  Readln; FreeAndNil(C);

  end.

结果:

Computer: cup = 1

Computer: cup = 2

Computer: cup = 3
Cellphone: teapot = kettle

Computer: cup = 4
iPhone: cup = 4

Computer: cup = 5
Cellphone: teapot = iPot
iPhone: teapot = iPot

第一部分符合 这个TiPhone 两个构造函数的定义如下:

  • 第一个构造函数重载继承的两个构造函数中的一个,并覆盖其同级构造函数。要实现此目的,请使用重载; override 以重载 TCellPhone 一个,同时覆盖另一个构造函数。
  • 完成后,第二个构造函数需要一个简单的覆盖来覆盖其同级构造函数。

This is a working implementation of the definitions wanted:

program OnConstructors;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type

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

TCellPhone = class(TComputer)
public
    constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;

TiPhone = class(TCellPhone)
public
    constructor Create(Cup: Integer); overload; override;
    constructor Create(Cup: Integer; Teapot: string); override;
end;

{ TComputer }

constructor TComputer.Create(Cup: Integer);
begin
  Writeln('Computer: cup = ', Cup);
end;

{ TCellPhone }

constructor TCellPhone.Create(Cup: Integer; Teapot: string);
begin
  inherited Create(Cup);
  Writeln('Cellphone: teapot = ', Teapot);
end;

{ TiPhone }

constructor TiPhone.Create(Cup: Integer);
begin
  inherited Create(Cup);
  Writeln('iPhone: cup = ', Cup);
end;

constructor TiPhone.Create(Cup: Integer; Teapot: string);
begin
  inherited;
  Writeln('iPhone: teapot = ', Teapot);
end;

var
  C: TComputer;

begin

  C := TComputer.Create(1);
  Writeln; FreeAndNil(C);

  C := TCellPhone.Create(2);
  Writeln; FreeAndNil(C);
  C := TCellPhone.Create(3, 'kettle');
  Writeln; FreeAndNil(C);

  C := TiPhone.Create(4);
  Writeln; FreeAndNil(C);
  C := TiPhone.Create(5, 'iPot');

  Readln; FreeAndNil(C);

  end.

with results:

Computer: cup = 1

Computer: cup = 2

Computer: cup = 3
Cellphone: teapot = kettle

Computer: cup = 4
iPhone: cup = 4

Computer: cup = 5
Cellphone: teapot = iPot
iPhone: teapot = iPot

The first part is in accordance with this. The definition of the TiPhone two constructors then proceeds as follows:

  • The first constructor is overloading one of the two constructors inherited and overriding its sibling. To achieve this, use overload; override to overload the TCellPhone one while overriding the other constructor.
  • That being done, the second constructor needs a simple override to override its sibling.
漫漫岁月 2024-10-04 01:07:16

对两者都使用重载,这就是我的做法,并且有效。

构造函数创建;重载; <-- 此处使用重载

构造函数值; Overload; <--这里

记住不要对两个不同的构造函数使用相同的名称

use overload on both, it's the way i do it, and it works.

constructor Create; Overload; <-- use overload here

constructor Values; Overload; <-- and here

remember not to use the same name for two different constructors

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