問題1:問題如題,自己做了測試
class Obj{ public $i; public function construct($t){ $this->i = $t; echo "執行建構函式$this->i"; echo "<br>"; } public function destruct(){ echo "執行解構函式$this->i"; echo "<br>"; } } $obj1 = new Obj(1); $obj2 = new Obj(2);執行建構函式1執行建構函式2執行解構函式2執行解構函式1
問題2:在子類中調用父類的構造方法是否只是對父類進行初始化,是否產生父類的對象?
======================================UPDATE======================================
找到一段理解比較深刻說法:
使用堆還是棧來儲存資料是由PHP引擎決定的,PHP開發人員不需要關心.
轉:
在PHP5的Zend Engine的實現中,所有的值都是在堆上分配空間,並且通過引用計數和垃圾收集來管理.
PHP5的Zend Engine主要使用指向zval結構的指標來操作值,在很多地方甚至通過zval的二級指標來操作.
而在PHP7的Zend Engine實現中,值是通過zval結構本身來操作(非指標).
新的zval結構直接被存放在VM的棧上,HashTable的桶裡,以及屬性槽裡.
這樣大大減少了在堆上分配和釋放記憶體的操作,還避免了對簡單值的引用計數和垃圾收集.
======================================UPDATE1======================================
找到了具體說明的地方
$p1 = new Person();對於這個條代碼,$p1 是對象名稱在棧記憶體裡面new Person()是真正的對象是在堆記憶體 裡面的,具體的請看:
這樣就解釋了為什麼先執行個體化的對象是後釋放的
new Person();實際返回的是一個對象的引用,然後引用賦值給$p1,$p1是儲存在棧中的變數,是一個指標,指向該對象在堆中分配的實體
這同時也解釋了php底層儲存變數是有一個hash符號表來維護變數的生命週期的,符號表中存有key=>value索引值對,key為變數名稱,key指向zval結構體,即value的首地址
建構函式和解構函式的執行事實上使用的是一個 棧 結構,由於 Obj(2) 是在後面建立的,因此位於棧頂的位置,按照棧 先進後出 的順序,銷毀時,Obj(2) 就是先被銷毀了。
看完樓主的題當時也是好多疑問,我也想知道為什麼不是
執行建構函式1執行建構函式1執行解構函式2執行解構函式2
PHP 5 引入了解構函式的概念,這類似於其它物件導向的語言,如 C++。解構函式會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執行
也就是流程是這樣的
Obj(1) 啟動,申請自己的記憶體空間與上下文環境Obj(2) 啟動,申請自己的記憶體空間與上下文環境Obj(2) 銷毀,記憶體回收Obj(1) 銷毀,記憶體回收
就是Obj(1) 先進後出一樣,他是後執行個體化,所以先銷毀
----------------------------Obj(1) Obj(2) Obj(2) Obj(1)----------------------------
問題2:在子類中調用父類的構造方法是否只是對父類進行初始化,是否產生父類的對象?
同樣手冊。繼承已為大家所熟知的一個程式設計特性,PHP 的物件模型也使用了繼承。繼承將會影響到類與類,對象與對象之間的關係。
比如,當擴充一個類,子類就會繼承父類所有公有的和受保護的方法。除非子類覆蓋了父類的方法,被繼承的方法都會保留其原有功能。
子類可以調用父類方法,繼承關係不存在執行個體化
我的想法:
問題1:持有對象引用的變數是存放在棧裡面的,棧是先進後出,變數obj2先與obj1銷毀
問題2:只會產生一個子類的對象
第一個問題:obj1和obj2很顯然都是存放在棧記憶體中,根據棧記憶體的特點先進後出,銷毀的時候自然是obj2先銷毀,也就是obj2的destruct先執行,然後才是obj1銷毀,即執行obj1的_desctruct。這也就解釋了你的順序問題。
第二個問題:不會產生父類對象,當你執行個體化一個子類的時候,父類的公有和受保護的方法會在執行個體化的對象上。因此你就可以調用父類的方法。