Почему нельзя переопределить construct при наследовании?
Потому что при наследовании нельзя изменять доступность функции. Если нужен синглтон, то ты по определению не сможешь унаследоваться от класса с открытым конструктором. А сделано это для того, чтобы объект любого класса, унаследованного от данного, гарантированно обладал всеми функциями родителя, в частности и возможностью создания новых объектов. Иначе теряется смысл наследования.
Вот тут хорошая дискуссия на эту тему: https://bugs.php.net/bug.php?id=40880
Как вариант, если хотите обернуть какой-то объект в синглтон, используйте делегирование а не наследованиеclass D
{
    public function __construct()
    {
    }
}

class S
{
    private static $instance = null;

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new D();
        }
        return self::$instance;
    }

    private function __construct()
    {
    }
}