析构函数的OOP概念?

时间:2015-07-02 07:25:48

标签: oop destructor

析构函数显示哪种面向对象的编程概念?例如,重载显示多态性。请解释你的答案的原因。我无法在网上找到这个......

4 个答案:

答案 0 :(得分:2)

大多数关键的OOP概念都是由析构函数显示的。如果我们将这些概念视为包括继承对象封装方法消息传递多态抽象组合授权打开递归。然后我们可以显示所有这些都在析构函数中发挥作用。

现在,通常“析构函数”表示在对象被销毁时自动调用的类中定义的方法*。这显然包括方法对象

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

struct SomeStruct
{
   SomeStruct* Next;
}

如果上面是用不支持面向对象设计的语言编写的,让我们在SomeStruct本身定义一个方法,并用全局delete()方法删除堆对象,那么要清理SomeStruct使用的所有内存,我们需要执行以下操作:

CleanUpSomeStruct(SomeStruct* toDelete)
{
  while(toDelete != null)
  {
    SomeStruct* deleteNext = someStruct->Next;
    delete(toDelete);
    toDelete = deleteNext;
  }
}

值得注意的是:

  1. 我们必须完成清除SomeStruct之外SomeStruct的工作。
  2. 没有什么可以阻止其他地方重复。也许不正确。
  3. 我们必须能够直接访问Next,增加我们可能会使用它做一些不明智的地方。
  4. 如果我们遇到不应删除Next的情况,那么虽然该知识可以存储在SomeStruct(可能是ownsNext字段)中,但该行为的逻辑在SomeStruct
  5. 的外部

    如果我们有析构函数那么:

    struct SomeStruct
    {
       SomeStruct* Next;
       ~SomeStruct()
       {
         if(Next != null) delete(Next);
       }
    }
    

    与上述相反:

    1. 清理SomeStruct的工作位于SomeStruct,接近其他SomeStruct相关代码。
    2. 可以有一个访问控制的概念,这可以防止在其他地方重复访问。
    3. 同样,访问控制可以阻止其他直接访问Next的情况,减少我们可能使用它做不明智的事情的数量。
    4. 如果我们遇到不应删除Next的情况,那么该逻辑可以存储在SomeStruct内部的一个位置。
    5. 另一方面,由于封装意味着我们可能无法访问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.
        }
      }
      

      这也要求析构函数 abstract ,一般意义上是对象的抽象模型的一部分(它可能与使用的abstract关键字无关在其他情况下强制执行抽象)。它们必须是多态,以便delete(Prev)调用Prev指向的对象中派生最多的析构函数,无论它是~SomeStruct()~SomeOtherStruct()还是另一个派生类型的析构函数,因此 Message Passing / Dynamic Dispatch 用于查找抽象/虚拟析构函数的正确实现。 (语言可以强制执行此操作,或者可以允许非虚拟析构函数作为优化)。

      最后析构函数与封装和开放递归交互,因为它们必须(可能隐式地)调用它们所组成的对象的析构函数,并且可能调用自己的方法来执行此操作。

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

答案 1 :(得分:1)

在OOP复活之前,存在释放程序资源的做法。即使在旧学校C中,没有任何对象,您也必须相应地释放内存,否则会导致内存泄漏,资源锁定或其他不良后果。

答案 2 :(得分:1)

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

引用维基百科

  

在面向对象的编程中,析构函数(有时缩短为   dtor)是一个在对象出现时自动调用的方法   破坏。

它的作用在清理时非常有用,就像释放程序更长时间使用的内存空间一样。由于大多数现代编程语言都具有自动垃圾收集功能,因此不再需要显式调用析构函数。

了解更多信息,请阅读GCFinalizer

希望它有所帮助。

答案 3 :(得分:0)

析构函数实现我们所知的" Resource Acquisition Is Initialization"