1、 當函數定義放在函數調用之後時,C程序的函數原型即聲明(function prototype)有時可以省略,而C++程序的函數原型則不能省略。
2、 內聯函數,函數調用中系統要進行現場處理,如果函數本身很短則現場處理佔用比重很大,此時定義內聯函數使得函數體直接嵌入函數調用處,消除附加現場處理。編譯時,編譯程序將內聯函數調用語句替換爲函數體代碼,並將形參替換爲實參,壞處是增加內存佔用空間,因此內聯函數一般適用於代碼較短的函數。在函數頭前加上inline即可,內聯函數體內不能有循環語句,switch語句和數據聲明,內聯函數必須定義在前,調用在後。
3、 引用作爲一般變量使用幾乎沒有實際意義,其最大的用處是用作函數形參。
4、 作用域有局部作用域,全局作用域和文件作用域三種。
作用域類型 |
相應變量 |
實現方式 |
作用範圍 |
局部 |
局部/內部 |
函數內部 |
函數內部 |
全局 |
全局/外部 |
函數外部+extern |
整個程序 |
文件 |
全局/外部 |
函數外部+static |
整個源文件 |
變量的作用域是從代碼空間的考慮,生存期是從時間考慮。作用域是指變量在源程序中的一段靜態區域,而生存期是指變量在程序執行過程中存在的一段動態時間。有些變量(如函數形參)沒有生存期,但有作用域,而有些變量雖然在生存期,但不在作用域內。
5、 C++中的變量有數據類型和存儲類型兩種屬性,C++內存分配方式有:自動,靜態和動態分配三種,分別對應活動存儲區(棧),靜態存儲區和自由存儲區(堆)。動態分配是一種完全由程序自身控制內存分配的方式。對於非動態內存分配的變量,變量採用哪種內存分配方式,是由聲明變量時指定的存儲類型和變量聲明語句所在的位置決定的。變量的存儲類型有auto,register,extern,static四種。
存儲類型 |
變量類型 |
存儲類型 |
生存期 |
Auto/未指定內部變量 |
內部 |
棧 |
函數內部 |
Register |
內部 |
寄存器(CPU) |
函數內部 |
Extern/未指定外部變量 |
外部 |
靜態存儲區 |
程序全局 |
Static |
內部或外部 |
靜態存儲區 |
程序全局 |
外部變量有定義性聲明和引用性聲明兩種聲明方式,定義性聲明表示定義變量,要爲變量分配內存空間,引用性聲明說明該變量已經在程序源文件中其他地方進行過定義性聲明。外部變量的定義性聲明只能放在函數的外部,引用性聲明可放在函數的外部,也可放在函數的內部。Extern主要用於外部變量的引用性聲明,而外部變量的定義性聲明可以不加extern。進行外部變量的extern引用性說明時一般不可以進行初始化,除非對該外部變量進行定義性聲明時沒有進行初始化。
Static修飾全局和局部變量作用不同,對於前者縮小了作用域,對於後者擴大了生存期。
6、 作用域限定符::解決局部變量和全局變量同名的問題,但是隻能用來訪問全局變量,不能用於訪問一個在語句塊外聲明的同名局部變量。
7、 條件編譯指令的用處:在調試程序時,經常需要利用輸出語句輸出一些調試信息,這時,可以在源程序開頭位置定義一個調試宏,在所有調試信息輸出語句前加上#ifdef條件編譯指令。在程序調試完之後,爲了不限是這些信息,只需刪除源程序開頭位置的宏定義指令,然後重新編譯程序即可。
8、 結構化程序設計是一種自頂向下,逐步求精的模塊化程序設計方法,是一種傳統的面向過程的程序設計方法。結構化程序設計將數據和過程分離,而面向對象的程序設計把數據和處理數據的過程當成一個整體即對象,前者是以功能爲中心劃分系統,後者是以數據爲中心來劃分系統具有更強的穩定性。
9、 在定義類時不能對成員變量進行初始化,因爲不能確定類中定義的成員變量時屬於哪一個對象。
10、如果在定義類時沒有定義構造函數和析構函數,編譯系統會自動添加一個默認的構造函數和析構函數,執行爲空。構造函數的定義通常放在類體內,自動成爲內聯函數。
11、類的不同對象的數據成員一般不同,此爲實例屬性;有的數據成員對所有對象都是一樣的,此爲類屬性。類屬性通過static關鍵字實現。靜態數據成員只佔一份內存,且即使沒有對象也會存在。靜態數據成員不能在構造函數或其他成員函數中對他們進行初始化,必須在類體外進行。在建立對象之前訪問靜態成員,則必須定義一個靜態成員函數,一般都是公有的,注意,靜態成員函數只能訪問類的靜態成員(變量和函數),而不能訪問非靜態成員,解決方法是將對象作爲靜態成員函數的的參數,然後在靜態成員函數中通過對象訪問非靜態成員。
12、在一個成員函數中經常需要調用其他非本類的成員函數,而有時需要把當前對象作爲參數傳遞給被調用函數,此時必須用到this指針,每個非靜態成員函數都有一個this指針。
13、一個類的友元函數需要在類定義中用friend聲明,爲了能夠在友元函數中訪問或修改類的私有成員,一個類的友元函數一般將該類的對象或對象引用作爲函數參數。還可以如此聲明一個類的友元類。友元是單向的,不交換不傳遞。
14、const常對象的數據成員的值在對象的整個生存期內不能被改變,必須利用構造函數進行初始化,且此後不能再被更新。常成員函數中只能調用常成員函數,通過常對象只能調用常成員函數。常數據成員只能通過構造函數初始化列表中設置初始值。
15、繼承方式
原屬性 繼承方式 |
Private |
Protected |
Public |
Private |
Private |
Private |
Private |
Protected |
Private |
Protected |
Protected |
Public |
Private |
Protected |
Public |
16、除非基類有默認的構造函數,否則派生類必須定義一個給基類的構造函數提供參數的構造函數。基類怎麼會沒有默認的構造函數呢?如果已經給基類自定義了構造函數,則基類不再有默認的構造函數。
17、處於同一層的各基類構造函數的執行順序取決於定義派生類時各基類的排列順序,而與定義派生類的構造函數時基類構造函數的排列順序無關。
18、多繼承容易導致二義性錯誤,通過d1.Base2::a這樣的方式消除太麻煩且浪費內存,於是出現了虛基類。當虛基類的間接派生類的構造函數採用顯式方式調用虛基類的構造函數時,該派生類的直接基類對虛基類的構造函數的調用將被C++編譯器忽略,如此可以保證不重複調用虛基類的構造函數,從而對虛基類的數據成員只初始化一次。
19、多態有編譯時多態和運行時多態兩種,前者是重載,後者是虛函數。
20、C++允許一個基類的指針指向其派生類的對象,反過來則不行。注意,即使將一個基類的指針指向派生類的對象,通過該指針也只能訪問派生類中從基類繼承來的共有成員,不能訪問派生類中新增加的成員,除非通過強制類型轉換將基類指針轉換爲派生類指針。
21、如果想通過指向派生類對象的基類指針調用派生類中覆蓋的成員函數,只有使用虛函數。當通過基類指針調用虛函數時,到底執行哪個類的成員函數完全由指針所指的對象決定。
22、構造函數不能被定義爲虛函數,因爲聲明派生類對象時也自動調用基類的構造函數。但可以將析構函數定義爲虛函數。當使用基類指針指向派生類對象,而派生類對象是使用new運算符創建的,當使用delete刪除派生類對象時,只調用基類的析構函數而不會調用派生類的析構函數,如果使用虛析構函數,無論指針所指的對象是基類對象還是派生類對象,程序都會調用對應的析構函數。
23、函數模板將數據類型參數化,編譯時函數模板本身並不產生可執行代碼,只有在函數模板被實例化時,編譯器才根據實參的數據類型進行類型參數的替換(與宏類似),生成一個真實的函數,然後再對這個函數進行編譯。類模板不是通過調用函數時實參的數據類型來確定類型參數的數據類型,而是通過使用類模板聲明對象時所給出的實際數據類型確定類型參數的數據類型。
24、運行庫文件,程序運行時所需要的庫文件,舊的是<iostream.h>,標準C++庫是<iostream> using namespace std
25、運行時類型識別(run-time type information, RTTI)是這樣一種機制:在程序運行時可以確定一個對象的類型。Dynamic_cast 運算符檢查一個基類指針是否指向其派生類對象,使用方式爲:dynamic_cast<指針類型>(指針);typeid運算符不僅可以確定一個對象是否屬於類繼承層次中某個類,還可以識別程序運行時一個對象的實際類型。
26、匈牙利命名法,a數組變量,c字符變量,x,y無符號整形變量,s字符串變量(不常用),sz以0結束的字符串變量,fn函數,Afx應用程序框架。