Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 静态变量被初始化两次_Php_Static - Fatal编程技术网

Php 静态变量被初始化两次

Php 静态变量被初始化两次,php,static,Php,Static,我一直认为static变量只初始化了一次,并将其值保留到脚本结束。然而,我在代码中遇到了一个bug,通过增加静态变量中的计数器来创建divID属性 下面是该bug的复制品: class Node { var $child = array(); public function test () { static $var = 0; $var++; echo $var,"\n"; foreach ( $this->

我一直认为
static
变量只初始化了一次,并将其值保留到脚本结束。然而,我在代码中遇到了一个bug,通过增加静态变量中的计数器来创建
div
ID属性

下面是该bug的复制品:

class Node {
    var $child = array();

    public function test () {
        static $var = 0;
        $var++;
        echo $var,"\n";
        foreach ( $this->child as $c )
            $c->test();
    }

    public function add_child ( $c ) {
        $this->child[] = $c;
    }
}
class Tree extends Node {
    public function __construct() {
        parent::add_child( new Node() );
        parent::add_child( new Node() );
    }
}
$tree = new Tree();
$tree->test();
上面有3个对
test()
的调用,预期的输出应该是

1 2 3

但是,变量
static$var
被初始化两次,产生以下输出:

1 1 2


有人能解释为什么会发生这种情况吗?

看起来静态变量
$var
树::测试()
和子
节点::测试()
调用。我不确定最好的解决办法。但是我做的是使
树::add_child()
添加class
树的子对象
而不是class
节点

class Node {
    var $child = array();

    public function test () {
        static $var = 0;
        $var++;
        echo $var,"\n";
        foreach ( $this->child as $c )
            $c->test();
    }

    public function add_child ( $c ) {
        $this->child[] = $c;
    }
}

class Tree extends Node {
    public static function createInitial() {
        $tree = new Tree();
        $tree->addChild();
        $tree->addChild();
        return $tree;
    }

    public function addChild() {
        parent::add_child( new Tree() );
    }
}

$tree = Tree::createInitial();
$tree->test();

这是一些令人讨厌的代码。当你遇到这样的问题时,最好退后一步,考虑另一种方法。否则,当您在6个月后回来添加新功能时,您将希望对键盘进行翻滚

在黑暗中拍摄,看起来(lsb)在这里工作。实例化的$tree对象创建了两个节点对象,每个节点对象都有一个test()方法,每个节点对象都绑定了一个
静态$var

$var每次调用的值

$tree->test()    $tree->child[0]->test()    $tree->child[1]->test()
1                1                          2
请注意,
$tree->child[1]->test()
调用输出一个2,这是因为
静态$var
变量将自身绑定到
$tree
对象,该对象在您进行初始
$tree->test()调用时已递增

我在原始代码中添加了一些输出,以演示这一点:

class Node {

    public $id;

    var $child = array();

    public function test () {

        static $var = 0;

        $var++;

        var_dump(sprintf('Id: %d | Var: %d', $this->id, $var));

        foreach ( $this->child as $key => $c ) {

            var_dump(sprintf('Container Object Id: %d | Child Id: %d | Var: %d', $this->id, $c->id, $var));

            $c->test();
        }
    }

    public function add_child ( $c ) {
        $this->child[] = $c;
    }
}
class Tree extends Node {
    public function __construct() {

        $node1 = new Node;
        $node1->id = 1;

        $node2 = new Node;
        $node2->id = 2;

        parent::add_child( $node1 );
        parent::add_child( $node2 );
    }
}
$tree = new Tree;

$tree->test();

// Output 
//  Conclusion: $var bound itself to $tree during runtime
string 'Id: 0 | Var: 1' (length=14)
string 'Container Object Id: 0 | Child Id: 1 | Var: 1' (length=45)
string 'Id: 1 | Var: 1' (length=14)
string 'Container Object Id: 0 | Child Id: 2 | Var: 1' (length=45)
string 'Id: 2 | Var: 2' (length=14)

为什么不使用静态类成员,也许这样可以解决您的问题。这是一个有趣的问题,但是在类中使用静态函数变量看起来很奇怪<代码>类节点{public static$counter=0;/*…*/}
@feeela我同意,但我倾向于仅在多个方法中使用该变量时使用类成员。它使阅读和调试变得更容易,特别是在大班情况下。又是什么原因呢???这不是一个合适的问题吗?@Waldermort请看我的answer@Waldermort由于您正在扩展该类,因此即使在多个类中也可以有效地使用该变量。它不像
那样有一个静态树::var属性和一个静态节点::var属性
。在哪里可以看到这两个类定义的静态属性?操作代码工作正常。好吧@voodoo417,我说错了,没有静态的
Tree::var
Node::var
属性,而是
Tree::test()
Node::test()
都是用OP的代码调用的。这是导致静态变量被启动两次的原因。请参阅手册中关于在函数(在本例中为-in-methods)中定义静态变量@voodoo417,我明确地说,我不确定这是否是最好的解决方案……但我试图解释问题并直接解决它,而不修改OP的逻辑。我仍然对我的答案感到满意,因为它直接解释并避免了OP提出的问题。你没有修改逻辑吗?您添加了新方法并更改了
树中的几乎所有代码。您还不了解在这两种情况下静态是如何工作的(方法中的静态属性和局部静态变量)。我建议您也阅读文档。祝你好运从未想过LSB,但它是有意义的。刚刚在PHP4上进行了测试,但结果相同。我只能猜测编译器被调用了两次,每个类方法调用一次。直到PHP5.3.0才引入“static”关键字,你确定它是php4吗?php4也不支持公共的、受保护的、私有的可见性属性,所以如果您真的使用php4,您应该会遇到语法错误。我使用它是因为我没有在本地安装它。所以,这可能不是一个准确的测试。我将稍后安装它并进行真正的测试。