面試題-面向對象篇

面向對象問題彙總

類的大小

Q:一個只含有虛函數的類的size爲多少?
A:參考這個博客
#類中的元素
0. 成員變量 1. 成員函數 2. 靜態成員變量 3. 靜態成員函數 4. 虛函數 5. 純虛函數
#影響對象大小的因素
0. 成員變量 1. 虛函數表指針(_vftptr) 2. 虛基類表指針(_vbtptr) 3. 內存對齊
**什麼都沒有,佔用一個字節**sizeof(空類的實例) = 1 byte ,如果有其他的,這個字節就不用算了。
類函數不佔用空間,加了構造函數和析構函數,sizeof(實例) = 1byte
有虛函數,實例中需要添加一個虛函數表的指針 sizeof(實例) = 4 byte
數據成員佔用空間 int4 char1 注意要對齊

Q:含虛函數類的虛函數表是存放在哪裏的
C++虛函數的具體實現原理(虛函數和虛函數表是熱門問題,一定要弄清楚其原理與實現)
實現編譯器處理虛函數表應該如何處理
A:
虛函數表vtbl實際上是一個指針數組,存放了虛函數的地址。指向虛函數表的指針vptr存在對象實例的最前面的位置。
虛函數指針是在構造函數執行時初始化的,虛函數表存放在了目標文件或者可執行文件的常量段中。虛函數表vtable在Linux/Unix中存放在可執行文件的只讀數據段中(rodata)
虛表在靜態區,因爲對每個類,所有對象共用虛表。

Q:C++的構造函數可以爲虛函數嗎?析構函數一般寫成虛函數的原因
A:
構造函數不能爲虛函數,而析構函數可以且常常是虛函數。
C++對象的構造,C++對象在三個地方構建:(1)函數堆棧;(2)自由存儲區,或稱之爲堆;(3)靜態存儲區。
無論在那裏構建,過程都是兩步:首先,分配一塊內存;其次,調用構造函數。
虛函數需要通過vtable來調用,而vtable是在構造函數中初始化的,所以構造函數不能爲虛函數。
析構函數需要寫成虛函數
防止只析構基類而不析構派生類的狀況發生,想析構子類中的重新定義或新的成員及對象,當然也應該聲明爲虛的

Q:什麼情況下要給類寫拷貝構造函數
A:
三種情況下會調用拷貝構造函數:
1) 一個對象作爲函數參數,以值傳遞的方式傳入函數體;
2) 一個對象作爲函數返回值,以值傳遞的方式從函數返回;
3) 一個對象用於給另外一個對象進行初始化(常稱爲賦值初始化);
需要定義拷貝構造函數
如果你需要定義一個非空的析構函數,那麼,通常情況下你也需要定義一個拷貝構造函數。
①對於凡是包含動態分配成員或包含指針成員的類都應該提供拷貝構造函數;②在提供拷貝構造函數的同時,還應該考慮重載”=”賦值操作符號。

Q:爲什麼用成員初始化列表會快一些
A:
foo(string s, int i):name(s), id(i){}
省去了臨時對象的存在,C++的賦值操作是會產生臨時對象的。對內置類型沒有多大差別。而類類型則減少了一次調用默認構造函數,直接調用拷貝構造函數。
必須用初始化列表的情況:1)類中const成員 2)其它類B作爲成員,類B禁止了賦值操作

Q:struct與class的區別
A:
默認的訪問控制:默認的繼承訪問權限(struct是public的,class是private的);默認的數據訪問控制(成員變量訪問控制struct是public的,class是private的)
struct更體現出一種數據結構,class更像【對象】
“class”這個關鍵字還用於定義模板參數,就像“typename”

Q:C++內存模型
A:
C語言:(由低地址到高地址)
a)正文段:用來存放程序執行代碼。通常,正文段是可共享的。另外,正文段常常是隻讀的,一次防止程序由於意外修改其自身。
b)初始化數據段:用來存放程序中已初始化的全局變量。數據段屬於靜態內存分配。
c)非初始化數據段:通常稱爲BSS段, 用來存放程序中未初始化的全局變量。BSS是英文Block Started by Symbol(由符號開始的塊)的簡稱。BSS段屬於靜態內存分配。 在程序開始執行之前,內核將此段中的數據初始化爲0或者空指針。
d)堆:堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc/free等函數分配內存時,新分配的內存就被動態添加到堆上 (堆被擴張)/釋放的內存從堆中被剔除(堆被縮減)。
e)棧:棧又稱堆棧, 存放程序的局部變量(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此以外,在函數被調用時,棧用來傳遞參數和返回值。由於棧 的先進後出特點,所以棧特別方便用來保存/恢復調用現場。
C++中,內存分成5個區,他們分別是自由存續區全局/靜態存續區常量存續區
a) 棧:內存由編譯器在需要時自動分配和釋放。通常用來存儲局部變量和函數參數。棧運算分配內置於處理器的指令集中,效率很高,但是分配的內存容量有限。在大多數C編譯器中,參數是由右往左入棧
b) 堆:內存使用new進行分配使用delete或delete[]釋放。如果未能對內存進行正確的釋放,會造成內存泄漏。但在程序結束時,會由操作系統自動回收。
堆是向高地址擴展數據結構,是不連續內存區域。空間比較大。系統是用鏈表來存儲空閒內存地址,鏈表遍歷方向是由低地址向高地址。會在這塊內存空間中首地址處記錄本次分配大小,這樣,代碼中delete語句才能正確釋放本內存空間。
c) 自由存儲區:使用malloc進行分配,使用free進行回收。和堆類似。
d) 全局/靜態存儲區:全局變量和靜態變量被分配到同一塊內存中,C語言中區分初始化和未初始化的,C++中不再區分了。(靜態局部變量生存期爲整個源程序,在其他函數中它是“不可見”的。)
e) 常量存儲區:存儲常量,不允許被修改。
Q:動態綁定
A:
多態,運行時確定地址,虛函數實現。

Q:new 和malloc的區別
1)類型不同:
malloc與free是C++/C語言的標準庫函數
new/delete是C++的運算符
2)分配內存的位置不同:
malloc函數從上動態分配內存
new操作符從自由存儲區(free store)上爲對象動態分配內存空間
自由存儲區不僅可以是堆,還可以是靜態存儲區
3)構造函數/析構函數
new/delete會調用對象的構造函數/析構函數以完成對象的構造/析構。
而malloc則不會。
參考鏈接:http://www.linuxidc.com/Linux/2016-01/127591.htm
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章