g++編譯os的memory'時不知道為什麼報錯。嘗試了很多方法(也可能搜錯了) 可以確定是純虛函數出現了問題 複習一下虛函數的子類構造和析構的過程吧(一年過去了) 允許派生類調用父類的同名函數而實現不同的功能,也叫動態聯編。 底層原理:虛函數表+虛函數表指針。每一個類都會對應一個虛函數表,一個存放 ...
g++編譯os的memory'時不知道為什麼報錯。嘗試了很多方法(也可能搜錯了)
可以確定是純虛函數出現了問題
複習一下虛函數的子類構造和析構的過程吧(一年過去了)
允許派生類調用父類的同名函數而實現不同的功能,也叫動態聯編。
底層原理:虛函數表+虛函數表指針。每一個類都會對應一個虛函數表,一個存放虛函數地址的虛函數表,並創建虛函數指針(vptr)來指向表。
虛函數和純虛函數的區別
純虛函數和虛函數都可以在子類中被重寫,他們的區別是:
1.純虛函數只有定義,沒有實現,而虛函數有定義,也有實現的代碼。純虛函數語法:virtual void print() = 0;
2.包含純虛函數的類不能定義其對象,而包含虛函數的則可以。
所以,純虛函數的作用就是在基類中定義這樣的介面但是又不想去實現,所以就只好設置純虛函數,因為只有這樣才能編譯通過。
純虛函數(pure virtual) :C++中包含純虛函數的類,被稱為是“抽象類”。抽象類不能使用new出對象,只有實現了這個純虛函數的子類才能new出對象。
虛函數指針的初始化過程
虛函數表的創建和虛函數指針的初始化都是在構造函數中進行的。當編譯器發現基類當中有虛函數存在時,就會為每個含有虛函數的類創建一個虛函數表(vtable),該表是一個一維數組,存放的是虛函數的地址,子類中如果沒有虛函數也會從基類中繼承虛函數表,虛表創建之後還會創建一個虛函數指針來指向虛表,即(vptr)。
當基類的析構函數定義為虛函數的時候,子類可以利用自己的析構函數來調用基類的析構函數,從而達到整個類的完全析構。
第一步:構造最頂層的基類部分
a、讓實例指向基類的虛函數表
b、構造基類實例成員變數
c、執行基類構造函數
第二步:構造派生部分(遞歸的)
a、讓實例指向派生類的虛函數表
b、構造派生類實例成員變數
c、執行派生類構造函數
析構時則是按相反的順序,就像這樣:
第一步:析構派生部分(遞歸的)
a、(實例已經指向派生類的虛函數表)
b、執行派生類析構函數
c、析構派生類實例成員變數
第二步:析構基類部分(遞歸的)
a、讓實例指向基類的虛函數表
b、執行基類析構函數
c、析構基類實例成員變數
根據上面的流程,構造函數和析構函數執行過程中,都有一段時間對象的虛函數指針指向基類虛函數表,如果在構造或者析構沒有完成的時候調用了該對象的虛函數,則是調用了基類的純虛函數。這種情況一般發生在多線程調用,構造或析構在一個線程,虛函數調用在另一個線程。
如果父類的函數不是純虛函數,而是有實現的虛函數,則是調用父類的虛函數,不會crash
所以我懷疑是多線程的問題(但是我代碼里沒有多線程啊)https://gitee.com/saucerdish(代碼可以看這裡os)
我懷疑會不會是不能用純虛類做全局變數呢,派生類做全局變數試試,發現也不行
讓我們找找出錯函數吧,沒有emmm
看看.rodata段呢
停下來啊啊啊啊在這
後來我覺得真的只是沒定義呢
試試extern一下這個東西吧
行吧,好像可以了