多繼承
乙個類繼承了多個類。
多繼承下的建構函式
先呼叫基類的建構函式,再呼叫子類建構函式,基類構造函式呼叫順序與宣告派生類時繼承基類的順序一致。在子類宣告建構函式時,可以在初始化列表顯示構造,也可以不寫,隱式呼叫基類的建構函式。
多繼承下的析構函式
析構先析構子類,再按照與宣告子類時繼承基類順序的相反順序來析構。析構順序與構造順序相反。
菱形問題
當多繼承的父類擁有更高的繼承層級時,可能產生更複雜的問題比如多繼承菱形。具體地如下圖:
舉例:
class file{};
class inputfile: public file{};
class outputfile: public file{};
class iofile: public inputfile, public outputfile{};
iofile
的兩個父類都繼承自file
,那麼file
的屬性(比如filename
)應該在iofile
中儲存乙份還是兩份呢? 這是取決於應用場景的,就file::filename
來講顯然我們希望它只儲存乙份,但在其他情形下可能需要儲存兩份資料。 c++還是一貫的採取了自己的風格:都支援!預設是儲存兩份資料的方式。如果你希望只儲存乙份,可以用virtual
繼承:
class file{};
class inputfile: virtual public file{};
class outputfile: virtual public file{};
class iofile: public inputfile, public outputfile{};
可能多數情況下我們都是希望virtual
的方式來繼承。但總是用virtual
也是不合適的,它有代價:
虛繼承類的物件會更大一些,因為含有虛函式的每個類會產生乙個虛表,類的物件需要乙個虛指標;
虛繼承類的成員訪問會更慢一些,因為需要尋找函式位址;
虛繼承類的初始化更反直覺一些。繼承層級的最底層(most derived class)負責虛基類的初始化,而且負責整個繼承鏈上所有虛基類的初始化。
對於多繼承的建議是:
如果能不使用多繼承,就不用他;
如果一定要多繼承,盡量不在裡面放資料,也就避免了虛基類初始化的問題。
名稱歧義
父類中有函式名稱一樣,子類呼叫時會有歧義,例如
class a;
class b;
class c: public a, public b;
c c;
c.func(); // 歧義!
必須這樣呼叫:
c.a::func();
典型的場景
public繼承自一些介面類,private繼承自那些實現相關的類。
虛函式虛函式是實現c++多型的一種重要手段,通過基類的指標或者引用指向的物件,會呼叫該物件實際型別中宣告的函式,為了這一特性,c++實現了虛函式表,每個物件儲存乙個虛函式指標,在執行過程中完成鏈編工作。通過virtual關鍵字來宣告。
純虛函式以=0結束,純虛函式的類不准例項化,它是抽象類,它提供了物件導向中的介面功能。
析構函式一般是虛函式
當基類指標指向派生類物件時,為了在析構時,能夠呼叫子類的析構函式,需要將基類的析構函式宣告為虛函式;從而達到釋放子類物件的記憶體,防止記憶體洩漏。
建構函式一般不能是虛函式
建構函式在執行前,物件的記憶體資訊都沒有,虛函式指標也沒有初始化,如果將建構函式宣告為虛函式,如何找到虛函式表?所以建構函式不能為虛函式,虛函式指標是在建構函式中初始化的;其次虛函式的目的是通過子類覆蓋基類,但是建構函式的順序是先構造基類再構造子類,所以必須先明確基類的型別,才能構造子類。
哪些函式不能是虛函式
前面說的建構函式;
還有友元函式,因為它不能被繼承;
靜態成員函式不能是虛函式,虛函式為實現多型需要this指標,但是靜態成員函式沒有this指標;
內聯函式,內聯函式要看編譯器。
友元友元關係:可以使用其他類或者函式作為友元,訪問自己的私有成員和保護成員;所以有友元類和友元函式;友元關係不能被繼承。
const用在什麼地方,它與巨集定義的區別
const可以修飾變數,引用,指標,成員變數,成員函式,還可以作為函式引數;使用const可以減少**出錯的概率,要注意區分常量指標和指標常量,可以對幾處使用地方進行闡述。
它跟巨集定義的區別,c++可以用const定義常量也可以用define定義常量。
const定義的常量是有資料型別的,define沒有,所以前者占用記憶體,在程式執行過程中,它只有乙份拷貝,它存在靜態儲存區的唯讀區;後者不占用記憶體;
編譯器可以對前者進行安全檢查,對後者只是在預處理階段進行字元替換;
巨集定義會出現邊際效應,const不會。
整合化除錯工具可以對const進行除錯,不能對define進行除錯。
初始化列表
在建構函式中,如果不在初始化列表中初始化類中變數,那麼就需要在建構函式體中對變數進行賦值初始化,進行賦值初始化之前,物件必須已經存在,所以在呼叫賦值建構函式之前,該物件必須已經由預設建構函式生成,這樣才能對其賦值。在初始化列表中初始化,呼叫的是複製建構函式,它只需要呼叫這乙個函式就可以生成乙個新的物件,少了一次預設建構函式的呼叫,對於資料密集型的類來說,這種方式更高效。
成員變數初始化順序:
按照它們在類**現的順序初始化,而不是在初始化列表中的順序初始化。
哪些東西必須放在初始化列表中:
常量成員,常量只能初始化,不能賦值,必須放在初始化列表裡面;
引用型別,引用必須在定義時初始化,它不能被重新賦值;
1. 空值:指標可以為空,懸空指標問題由此而來;引用無法為空,只有存在的資料物件才有別名。
2. 改變:指標可以更改;引用(別名)則不能易主。
3. 大小:指標是實體,大小為4位元組(32位系統);引用僅為別名,大小為其依附資料物件的大小。
4. 安全:指標沒有型別檢查;引用有型別檢查。
5. 訪問:指標間接訪問物件;引用直接訪問物件。
小結:在函式引數傳遞中,指標與引用均可解決大塊資料或物件傳遞效率低和空間開銷大的問題。
準備面試一
這次金蝶的面試爭取到了幾天的準備時間,順帶一句上次一公司通知叫她發郵件答應了沒發,這樣的公司不去也罷。面試我是這樣理解的,全力以赴,深入 準備,以成功為導向的經歷才有用,才能叫經驗。不能為失敗為目的,消極應對。自信自然出色。真誠贏得成功。前天看了常考的sql語句題目,昨天看了oracle調優,今天大...
bigo測試一面
居然不用自我介紹 介紹一下你的專案 你在工作中 測試部 的角色 你們需求評審是怎麼做的?怎麼去解決在特定排期內測試資源不足的問題 在技術評審中你的角色是什麼?從你參加的技術評審中你有哪些實際的收益 你們有做介面自動化了嗎?怎麼測試介面的併發 你們服務的併發是多少 你們有沒有編寫測試用例的標準?怎麼保...
2012面試準備 2012 10 26面試準備
c 1 什麼純虛函式?首先,二者申明不一樣。virtual void test void 虛函式 virtual void test void 0 純虛函式 其次,如果乙個類包含了乙個純虛函式 哪怕只有乙個是純虛函式 那麼它就是乙個抽象類 就是不能生成具體的物件!但如果類中只包含虛函式,那麼是可以定...