網易面經 基礎知識

2021-08-06 06:59:08 字數 3249 閱讀 3310

(靜態和動態,然後分別敘述了一下虛函式和函式過載)

靜態:函式過載;

動態:虛函式

(就是問了一下基類與派生類指標和引用的轉換問題)

1. 為每乙個包含虛函式的類設定乙個虛表(vtable)每當建立乙個包含有虛函式的類或從包含虛函式的類派生乙個類時,編譯器就會為這個類建立乙個vtable。在vtable中,編譯器放置了這個類中,或者它的基類中所有已經宣告為 virtual 的函式的位址。如果在這個派生類中沒有對基類中宣告為 virtual 的函式進行重新定義,編譯器就使用基類的這個虛函式的位址。而且所有vtable中虛函式位址的順序是完全相同的。

2. 初始化虛指標(vptr)然後編譯器在這個類的各個物件中放置vptr。vptr在物件的相同的位置(通常都在物件的開頭)。vptr必須被初始化為指向相應的vtable。

3. 為虛函式呼叫插入** 當通過基類的指標呼叫派生類的虛函式時,編譯器將在呼叫處插入相應的**,以實現通過vptr找到vtable,並根據vtable中儲存的正確的虛函式位址,訪問到正確的函式。

虛函式呼叫過程:

1. 如果我們的程式是通過指向物件的指標或者是引用來呼叫該物件的虛函式,則在呼叫虛函式的過程需要查表(虛函式表)來呼叫真正的函式。

2. 呼叫的不是虛函式則不需要查表,在編譯時即可確定呼叫的是那個函式。

3. 如果是通過物件來呼叫則對任何型別的函式都不需要查表。

4. 虛指標是在物件的建構函式中初始化的(所以建構函式不能是虛函式)。

物件在記憶體中的存在形式:

1.c++物件(基類物件)的記憶體布局是:物件的記憶體位址(&a)所指向的記憶體中的前四個位元組中存放的是該物件的虛函式表的首位址(前提是該物件有虛函式),接下來的記憶體中依次存放該物件的資料成員(非靜態的資料成員)。

虛函式的存放順序與函式的順序是相同的。

2.派生類的物件的記憶體布局是:前四個位元組依然存放虛表指標,虛表中首先存放父類的虛函式位址,注意,由於派生類中也可能有①自己的虛函式,同時派生類也可以②重寫父類的虛函式,虛函式表的分布如何:

對於情況一而言,將派生類新增加的虛函式位址依次新增到虛表(虛表中已經有父類的虛函式位址)的後面。

對於情況二而言,如果派生類重寫了父類的虛,則將重寫後的虛函式位址替換掉父類原來的虛函式位址,如果沒有重寫,則按照父類的虛表順序存放虛函式位址

接下來的記憶體中依次存放該物件的父類的資料成員(非靜態的資料成員),然後再存放派生類自己的資料成員。(還有記憶體對齊的問題)

(四種型別轉換,分別舉例說明)

1-const_cast,字面上理解就是去const屬性。

const_cast是一種c++運算子,主要是用來去除復合型別中const和volatile屬性(沒有真正去除)。

變數本身的const屬性是不能去除的,要想修改變數的值,一般是去除指標(或引用)的const屬性,再進行間接修

2-static_cast

與c語言強制轉換不同的是,c風格的強制型別轉換(type cast)很簡單,不管什麼型別的轉換統統都能轉,而static_cast會進行型別檢查,若倆不相干的類型別轉換就不行。

3-dynamic_cast

命名上理解是動態型別轉換。如子類和父類之間的多型型別轉換。

dynamic_cast會先檢查是否能轉換成功,能成功則轉換,不能則返回0

什麼時候dynamic_cast是安全的?如果父類指標或引用指向的是乙個子類物件時,這時將指標轉換為子類指標是安全的

什麼時候不安全?父類的指標或引用沒有指向乙個子類物件,而是指向乙個父類物件的時候,這個指標轉換為子類物件將是不安全的

4-reinterpreter_cast

僅僅重新解釋型別,但沒有進行二進位制的轉換。

不同型別的指標型別轉換用reinterpreter_cast,最普通的用途就是在函式指標型別之間進行轉換

(讓把操作符過載函式原型說一遍)(需要補充)

函式型別 operator 運算子(形參表) 

結構體也要對齊;
(就是四種情況說了一下)

指向const的指標(指標指向的內容不能被修改)const關健字總是出現在 * 的左邊而const指標(指標本身不能被修改)const關健字總是出現在 * 的右邊,那不用說兩個const中間加個*肯定是指標本身和它指向的內容都是不能被改變的。

(純虛函式如何定義,為什麼析構函式要定義成虛函式)

虛繼承

解決鑽石繼承中,派生類中有多分祖類裡的類成員(資料和方法)

在實現多型時,當用基類操作派生類,在析構時防止只析構基類而不析構派生類的狀況發生。採用徐析構函式後,先釋放派生類資源,再釋放基類資源

(講了一下內聯函式的優點以及和巨集定義的區別)

內聯函式在執行時可除錯,而巨集定義不可以;

編譯器會對內聯函式的引數型別做安全檢查或自動型別轉換(同普通函式),而巨集定義則不會;

內聯函式可以訪問類的成員變數,巨集定義則不能;

在類中宣告同時定義的成員函式,自動轉化為內聯函式。

優點是提高執行時間效率,減少函式進出棧;,缺點是增加了空間開銷

(主要講了const的用處,有那些優點)

const型別的變數在宣告的時候一定要進行初始化,否則會報錯。

最好時間複雜度,平均時間複雜度

extern 「c」的主要作用就是為了能夠正確實現c++**呼叫其他c語言**。加上extern 「c」後,會指示編譯器這部分**按c語言的進行編譯,而不是c++的。由於c++支援函式過載,因此編譯器編譯函式的過程中會將函式的引數型別也加到編譯後的**中,而不僅僅是函式名;而c語言並不支援函式過載,因此編譯c語言**的函式時不會帶上函式的引數型別,一般之包括函式名。

(大體講了 一下,繼承、多型、封裝、異常處理等

網易面經總結

1.執行緒池的threadpoolexecutor的主要引數有哪些,詳細介紹了一下任務佇列 2.執行緒建立的幾種方式以及區別 3.hashmap的底層實現,以及1.7和1.8之間的區別 4.執行緒安全的容器有哪些 5.concurrenthashmap的底層實現原理,以及1.8是如何操作的 6.異常...

網易unity面經 有道

我面試的unity開發實習生,網易有道,今年第一次招人。1.你覺得unity單場景好還是多場景好?優質回答 2 xlua熱更新流程 4 動畫 我用的是dotween外掛程式 5 記憶體優化 6 unity的ar外掛程式有哪些?你都了解什麼?本人只會vuforia。更多請參考 以上回答都不是本人回答,...

網易雷火面經1

2020.5.8 網易雷火前端1面 時長 40mins 1.自我介紹 2.說幾個專案 3.threejs 對模型中的點選事件如何實現 4.繼承,有哪些方法 5.作用域 6.去重 7.閉包 8.bfc 9.tagname輸出的是大寫還是小寫 大寫 tagname 10.display none 和 v...