1、C++裏的鑽石結構
class A { };
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { };
2、long和float都是用四個字節表示
3、關鍵字volatile的作用
一個定義爲volatile的變量是說這變量可能會被意想不到的改變,這樣,編譯器就不會去假設這個變量的值了。精確的說就是,優化器在用到這個變量時必須每次都小心的重新讀取這個變量的值,而不是保存在寄存器裏的備份。
4、抽象類和接口的區別
抽象類是特殊的類,只是不能被實例化(將定義了純虛函數的類稱爲抽象類);除此之外,抽象類具有類的其它特性;重要的是抽象類可以包含抽象類和抽象方法,這是普通類所不能的,但同時也可以包含普通的方法。抽象方法只能聲明於抽象類中,且不包含任何實現,派生類必須覆蓋它們。另外,抽象類可以派生自一個抽象類,可以覆蓋基類的抽象方法也可以不覆蓋,如果不覆蓋,則其派生類必須覆蓋它們。雖然不能定義抽象類的實例,但是可以定義它的指針,這正是抽象類實現接口的重點所在。
接口是一個概念,它在C++中用抽象類實現,在C#和Java中用interface來實現。
接口是引用類型的,類似於類,和抽象類的相似之處有三點。
1)不能實例化
2)包含未實現的方法和聲明
3)派生類必須實現未實現的方法,抽象類是抽象方法,接口則是所有成員(不僅是方法,包括其它成員)
另外,接口有如下特性:
接口除了可以包含方法之外,還可以包含屬性、索引器、事件,而這些成員都被定義爲公有的。除此之外,不能包含其它的任何成員,例如:常量、域、構造函數、析構函數,靜態成員。
5、sizeof和strlen的區別
sizeof是一種單目運算符,而strlen是一個函數。
sizeof的操作數可以是數據類型、函數、變量、表達式
strlen的應用則不像sizeof那麼廣泛,參數必須是char *型的指針
6、什麼是野指針,什麼情況下會產生野指針,如何避免?
野指針是指向不可用內存區域的指針。通常對野指針進行操作的話,會產生不可預知的錯誤。
野指針的產生有三種情況:
1)指針變量未被初始化
2)動態內存中指針被free或delete釋放後沒有被置爲null
3)指針操作超越了變量的作用範圍
避免:我們需要將指針初始化爲NULL,用完後也爲其賦值NULL
拷貝構造時防止淺拷貝
7、面向對象的三個要素五個原則
三要素:繼承封裝多態
封裝:將抽象得到的數據和方法相結合,形成一個有機整體,使用者不必瞭解具體的實現細節,而只要通過外部接口,一特定的訪問權限來使用類的成員
繼承:繼承可以使子類具有父類的各種屬性和方法,而不需要編寫相同的代碼
多態:不同的對象調用相同的函數會產生不同的效果,允許將子類類型的指針賦給父類類型的指針
五元則:單一職責原則
應該有且僅有一個原因引起類的變更
開放封閉原則
對擴展開放,對修改封閉
里氏替換原則
子類可以擴展父類的功能,但不能改變父類的功能
依賴倒置原則
對抽象進行編程,不要對實現進行編程,這樣就降低了業務與實現模塊間的耦合
接口隔離原則
使用多個專門的接口總比使用一個單一的接口好
8、與類相關的sizeof操作
定義一個 空的類,沒有任何的成員變量和成員函數,對該類型求sieof,得到的結果是多少?
答案是1,空類型的實例中不包含任何信息,本來求sizeof應該是0,但是當我們聲明該類型的實例的時候,它必須在內存中佔有一定的空間,否則無法使用這些實例。至於佔用多少內存,由編譯器決定。Visual Studio中每個空類型的實例佔用1字節的空間。
如果在該類型中添加一個構造函數和析構函數,再對該類型求sizeof,得到的結果又是多少?
和前面一樣,還是1。調用構造函數和析構函數只需要知道函數的地址即可,而這些函數的地址只與類型相關,而與類型的實例無關,編譯器也不會因爲這兩個函數而在實例內添加額外的信息。
那如果把析構函數標記爲 虛函數呢?
C++的編譯器一旦發現一個類型中有虛擬函數,就會爲該類型生成虛函數表,並在該類型的每一個實例中添加一個指向虛函數表的指針。在32位機器上,一個指針佔4個字節的空間。
9、不允許複製構造函數傳值
如果允許複製構造函數傳值,就會在複製構造函數內調用複製構造函數,就會形成無休止的遞歸調用從而導致棧溢出