gpt4 book ai didi

php - PHP 类构造函数中的作用域展开

转载 作者:可可西里 更新时间:2023-10-31 22:47:37 25 4
gpt4 key购买 nike

我正在学习 PHP 类和异常,并且,由于具有 C++ 背景,以下内容让我觉得很奇怪:

当派生类的构造函数抛出异常时,看起来基类的析构函数没有自动运行:

class Base
{
public function __construct() { print("Base const.\n"); }
public function __destruct() { print("Base destr.\n"); }
}

class Der extends Base
{
public function __construct()
{
parent::__construct();
$this->foo = new Foo;
print("Der const.\n");
throw new Exception("foo"); // #1
}
public function __destruct() { print("Der destr.\n"); parent::__destruct(); }
public $foo; // #2
}

class Foo
{
public function __construct() { print("Foo const.\n"); }
public function __destruct() { print("Foo destr.\n"); }
}


try {
$x = new Der;
} catch (Exception $e) {
}

这打印:

Base const.
Foo const.
Der const.
Foo destr.

另一方面,如果构造函数中出现异常(在 #1),成员对象的析构函数正确执行。现在我想知道:如何在 PHP 的类层次结构中实现正确的范围展开,以便在发生异常时正确销毁子对象?

此外,似乎没有办法在所有成员对象都被销毁后 运行基本析构函数(在#2)。也就是说,如果我们删除 #1 行,我们会得到:

Base const.
Foo const.
Der const.
Der destr.
Base destr.
Foo destr. // ouch!!

如何解决这个问题?

更新:我仍然愿意接受更多的贡献。如果有人有充分的理由解释为什么 PHP 对象系统从不要求 正确的销毁序列,我将为此提供另一个赏金(或仅针对任何其他有说服力的答案)。

最佳答案

我想解释为什么 PHP 以这种方式运行,以及为什么它实际上有(某些)意义。

在 PHP 中,一旦不再有对对象的引用,对象就会被销毁。可以通过多种方式删除引用,例如通过 unset() 变量,通过离开范围或作为关闭的一部分。

如果你理解了这一点,你就可以很容易地理解这里发生了什么(我会先解释没有异常的情况):

  1. PHP 进入关闭状态,因此所有变量引用都被删除。
  2. $x 创建的引用(到 Der 的实例)被删除时,对象被销毁。
  3. 调用派生析构函数,调用基析构函数。
  4. 现在从 $this->fooFoo 实例的引用被删除(作为销毁成员字段的一部分。)
  5. 也不再有对 Foo 的引用,因此它也被销毁并调用析构函数。

想象一下,这不会以这种方式工作,并且成员字段会在调用析构函数之前被销毁:您无法再在析构函数中访问它们。我严重怀疑 C++ 中是否存在这种行为。

在异常情况下,您需要了解对于 PHP 而言,类的实例从未真正存在过,因为构造函数从未返回。你怎么能破坏从未 build 过的东西?


我该如何解决?

你不知道。你需要一个析构函数这一事实可能是糟糕设计的标志。事实上,销毁命令对您来说非常重要,这一点更重要。

关于php - PHP 类构造函数中的作用域展开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7470969/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com