I'm learning PHP classes and exceptions, and, coming from a C++ background, the following strikes me as odd:
When the constructor of a derived class throws an exception, it appears that the destructor of the base class is not run automatically:
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) {
}
This prints:
Base const.
Foo const.
Der const.
Foo destr.
On the other hand, the destructors of member objects are executed properly if there is an exception in the constructor (at #1
). Now I wonder: How do you implement correct scope unwinding in a class hierarchy in PHP, so that subobjects are properly destroyed in the event of an exception?
Also, it seems that there's no way to run the base destructor after all the member objects have been destroyed (at #2
). To wit, if we remove line #1
, we get:
Base const.
Foo const.
Der const.
Der destr.
Base destr.
Foo destr. // ouch!!
How would one solve that problem?
Update: I'm still open to further contributions. If someone has a good justification why the PHP object system never requires a correct destruction sequence, I'll give out another bounty for that (or just for any other convincingly argued answer).