我學習PHP類和異常,而且,從C來++背景,以下令我奇怪:範圍展開的PHP類的構造函數
當一個派生類的構造函數拋出異常,它出現基類的析構函數不會自動運行:
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中實現析構函數,所以也許這不是什麼大問題。不過你確實提出了一個很好的問題。 –
@Jani:坦率地說,考慮到它們的設計方式,我明白你爲什麼不想*使用析構函數。我只是想知道他們爲什麼看起來如此糟糕,以及除了「不要使用這部分語言」之外,是否有任何常見的成語來規避這種設計缺陷?:-S –
同意Jani:在PHP中編寫析構函數確實毫無意義,因爲沒有任何東西可以泄漏。來自C++,你可能將析構函數視爲一個非常深思熟慮的工具,用於解決他們無意解決的問題。 – Jon