【问题标题】:Does Delphi call inherited on overridden procedures if there is no explicit call如果没有显式调用,Delphi 调用是否继承于被覆盖的过程
【发布时间】:2010-09-08 09:32:34
【问题描述】:

如果代码中没有显式调用,Delphi 调用是否继承于重写的过程,即(继承;),我有以下结构(从超类到子类)

TForm >> TBaseForm >> TAnyOtherForm

项目中的所有表单都将派生自 TBaseForm,因为这将具有用于每个表单的所有标准设置和破坏性部分(安全性、验证等)。

TBaseForm 有 onCreate 和 onDestroy 程序以及执行此操作的代码,但如果有人(即我)忘记将继承添加到 TAnyOtherForm 上的 onCreate 中,Delphi 会为我调用它吗?我在网上找到了说它不是必需的参考资料,但没有地方说如果代码中省略它是否会被调用。

如果它确实为我调用了继承,它什么时候会调用它?

【问题讨论】:

    标签: delphi oop inheritance


    【解决方案1】:

    不,如果您将调用保留为继承,它将不会被调用。否则不可能覆盖一个方法并完全忽略它的父版本。

    【讨论】:

      【解决方案2】:

      必须显式地进行继承调用。一般来说,没有一种语言会在等效情况下自动调用继承的函数(不包括类构造函数)。

      很容易忘记在类构造函数中进行继承调用。在这种情况下,如果基类需要初始化任何数据,您就有可能发生访问冲突。

      也许您可以在 TBaseForm 类中覆盖 DoCreate 和 DoDestory,这样您就可以确保执行某些代码,而不管子类的实现如何。

      // interface
      
      TBaseForm = Class(TForm)
      ...
      Protected
          Procedure DoCreate(Sender : TObject); Override;
      End
      
      // implementation
      
      Procedure TBaseForm.DoCreate(Sender : TObject);
      Begin
          // do work here
      
          // let parent call the OnCreate property  
          Inherited DoCreate(Sender);
      End;
      

      【讨论】:

        【解决方案3】:

        值得一提的是,在Destroy中不调用继承的任何对象都会导致内存泄漏。有一些工具可以在您的源代码中检查这一点。

        【讨论】:

          【解决方案4】:

          正如其他人所指出的那样,不会隐式调用继承的代码。您必须明确调用它。这为您提供了一些有用的灵活性。例如,您可能希望在继承代码之前执行一些预处理代码,然后再执行一些后处理代码。这可能看起来像:

          procedure TMyCalcObject.SolveForX;
          begin
            ResetCalcState;
            inherited SolveForX;
            PostProcessSolveForX;
          end;
          

          【讨论】:

            【解决方案5】:

            没有。这就是覆盖的全部意义。

            【讨论】:

              【解决方案6】:

              Inherited 必须在后代对象以及可视形式继承中显式调用。如果您使用类完成,那么如果您将定义标记为覆盖(但不是重新引入),它会自动添加继承。如果您使用可视表单继承,那么当您通过表单编辑器添加新的事件处理程序时,它也会添加继承。

              【讨论】:

                【解决方案7】:

                您必须明确调用它。这提供了很大的灵活性,因为您可以选择在代码中的哪个点调用继承的方法。但这也是错误的一大来源。很容易忘记调用继承的函数,编译器无法判断是故意还是忘记了。

                应该有某种指令“skip_inherited”告诉编译器你不想调用继承的方法。

                如果没有找到“inherited”或“skip_inherited”,编译器会很容易地报告错误。那意味着你忘记了。但不幸的是,CodeGear 中没有人想到这一点。

                【讨论】:

                  猜你喜欢
                  • 2019-08-05
                  • 2017-05-03
                  • 2015-10-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多