析构函数的OOP概念?

析构函数的OOP概念?,oop,destructor,Oop,Destructor,析构函数显示了哪个面向对象的编程概念?例如,重载显示多态性。请解释你回答的原因。我在网上的任何地方都找不到这一点。释放程序资源的做法在OOP出现之前就存在了。即使在老式的C语言中,如果没有任何对象,也必须相应地释放内存,否则会出现内存泄漏、资源锁定或其他不好的后果。析构函数实现了我们称之为“的概念是垃圾收集。在oop中,您可以将其与释放以前分配给任何不再需要或删除的对象的空间联系起来 引用维基百科 在面向对象编程中,析构函数(有时简称为 dtor)是一种方法,当对象 毁灭 它的作用在清理中很有用

析构函数显示了哪个面向对象的编程概念?例如,重载显示多态性。请解释你回答的原因。我在网上的任何地方都找不到这一点。

释放程序资源的做法在OOP出现之前就存在了。即使在老式的C语言中,如果没有任何对象,也必须相应地释放内存,否则会出现内存泄漏、资源锁定或其他不好的后果。

析构函数实现了我们称之为“

的概念是垃圾收集。在oop中,您可以将其与释放以前分配给任何不再需要或删除的对象的空间联系起来

引用维基百科

在面向对象编程中,析构函数(有时简称为 dtor)是一种方法,当对象 毁灭

它的作用在清理中很有用,比如释放程序不再使用的内存空间。由于大多数现代编程语言都具有自动垃圾收集功能,因此不再需要显式调用析构函数

阅读和了解更多信息


希望能有所帮助。

大多数关键OOP概念都由析构函数显示。如果我们将这些概念考虑为继承、对象、类、封装、方法、消息传递、多态、抽象、合成、委托和开放递归。然后我们可以展示它们在析构函数中的作用

现在,通常“析构函数”是指在类中定义的方法,该类在对象被销毁时自动调用*。这显然涵盖了方法、对象和类

析构函数封装了清理逻辑。考虑一个可以指向另一个结构的结构:

struct SomeStruct
{
   SomeStruct* Next;
}
如果上述语言不支持面向对象设计,允许我们在
SomeStruct
本身上定义一个方法,并使用全局
delete()
方法删除堆对象,那么要清理SomeStruct使用的所有内存,我们需要执行如下操作:

CleanUpSomeStruct(SomeStruct* toDelete)
{
  while(toDelete != null)
  {
    SomeStruct* deleteNext = someStruct->Next;
    delete(toDelete);
    toDelete = deleteNext;
  }
}
值得注意的是:

  • 我们必须在
    SomeStruct
    之外清理
    SomeStruct
  • 没有什么可以防止这种情况在其他地方被复制。也许不正确
  • 我们必须能够直接访问
    Next
    ,增加我们可能用它做不明智事情的地方的数量
  • 如果我们有不应该删除
    Next
    的情况,那么虽然这些知识可以存储在
    SomeStruct
    中(可能是
    ownsNext
    字段),但对这些知识采取行动的逻辑是在
    SomeStruct
    之外的
  • 如果我们有析构函数,那么:

    struct SomeStruct
    {
       SomeStruct* Next;
       ~SomeStruct()
       {
         if(Next != null) delete(Next);
       }
    }
    
    与上述情况相比:

  • 清理
    SomeStruct
    的工作在
    SomeStruct
    中,靠近其他
    SomeStruct
    相关代码
  • 有一个访问控制的概念是可能的,它可以防止这种情况在其他地方被复制
  • 同样,访问控制可以阻止其他直接访问
    Next
    的情况,从而减少我们可能使用它做不明智事情的地方
  • 如果我们有不应该删除
    Next
    的情况,那么该逻辑可以存储在
    SomeStruct
    内部的一个位置
  • 另一方面,由于封装意味着我们可能无法访问
    Next
    ,因此封装意味着我们拥有能够清理对象的析构函数(或者给方法一个明确的“清理自己”)方法,但必须记住每次都调用它,并且知道它是否在给定的情况下存在,并且它的调用是一个拖拽)。显然,如果我们有自动垃圾收集,这个例子并不重要,但是在那些情况下,如果封装阻止了必要的清理任务中的外部代码,我们同样需要某种析构函数

    同样,如果我们有继承,我们需要有可继承的析构函数,可以隐式或显式地传递清理任务:

    struct SomeOtherStruct : SomeStruct
    {
      SomeStruct* Prev;
      ~SomeOtherStruct()
      {
        if(Prev != null) delete(Prev);
        base.~SomeStruct(); // Possibly this would be implicit in that
                            // the language would automatically make a
                            // call to a destructor finish with a call
                            // to any base destructors.
      }
    }
    
    这还要求析构函数在一般意义上是抽象的,即作为对象的抽象模型的一部分(它可能与用于在其他上下文中强制抽象的
    抽象
    关键字无关)。它们必须是多态的,
    delete(Prev)
    调用
    Prev
    指向的对象中最派生的析构函数,无论它是
    ~SomeStruct()
    ~SomeOtherStruct()
    还是另一个派生类型的析构函数,因此,使用消息传递/动态分派来找到抽象/虚拟析构函数的正确实现。(一种语言可以强制执行这一点,或者允许非虚拟析构函数作为优化)

    最后,析构函数与封装和开放递归交互,因为它们必须(可能隐式地)调用由它们组成的对象的析构函数,并可能调用它们自己的方法来实现这一点


    *对于使用确定性对象删除的语言/框架来说,“当对象被销毁时”是一个比使用非确定性垃圾收集的语言/框架更简单的概念。通常,在后一种情况下,“析构函数”指的是在非确定性收集最终发生时运行的方法(假设它曾经发生过),但如果它们有一个单独的“处置”方法,可以是确定性的,那么它可以服务于确定性析构函数所服务的一些rôle。特别是,虽然确定性析构函数在提供RAII技术方面很有用,但非确定性析构函数却没有,任何类似RAII的方法的使用都必须是确定性处理的一部分。

    如果销毁是确定性的,则可以使用它来实现RAII(不过,如果有什么应该称之为资源释放的话,那就是破坏)。